进程间通信

作者: 狼之足迹 | 来源:发表于2016-08-15 18:46 被阅读40次

    每个进程都有各自的进程地址空间,所以进程之间的交互就需要通过内核了.

    进程间通信方式:

    管道

    命名管道

    XSI IPC:

    消息队列

    信号量

    共享内存


    管道pipe

    int pipe(int pipe fd[2]);

    fd[0]    读文件描述符

    fd[1]    写文件描述符

    父进程创建管道,fork[子进程获得父进程打开的描述符]

    管道只能实现单方向通信;

    且因为实现,仅能父子进程间通信.或者同宗族进程通信,且其必须从公共祖先获得管道

    命名管道

    在文件系统中创建一个管道文件.使得进程都可以访问得到

    shell方式创建命名管道

    mknod - make block or character special files

    mkfifo - make FIFOs (named pipes)

    函数创建

    int mkfifo(const char *pathname, mode_t mode);      

    int mkfifoat(int dirfd, const char *pathname, mode_t mode);

    XSI IPC


    消息队列

    消息队列提供了一种向另一进程发送数据块的方法

    消息队列是基于消息的,而管道是基于字节流的

    lang@liang:~$ cat /proc/sys/kernel/msgmax  最大长度
    8192
    lang@liang:~$ cat /proc/sys/kernel/msgmnb 每个消息的总字节数
    16384
    lang@liang:~$ cat /proc/sys/kernel/msgmni  消息队列的总数
    32000

    内核为IPC维护的数据结构,消息队列,信号量,共享内存都有一个以下的数据类型

    #cat /usr/include/linux/ipc.h

    IPC对象数据结构

    struct ipc_perm
    {
    __kernel_key_t key;
    __kernel_uid_t uid;
    __kernel_gid_t gid;
    __kernel_uid_t cuid;
    __kernel_gid_t cgid;
    __kernel_mode_t mode;
    unsigned short seq;
    };

    msg对象数据结构

    struct msqid_ds {

    struct ipc_perm msg_perm;

    struct msg *msg_first; /* first message on queue,unused  */

    struct msg *msg_last; /* last message in queue,unused */

    __kernel_time_t msg_stime; /* last msgsnd time */

    __kernel_time_t msg_rtime; /* last msgrcv time */

    __kernel_time_t msg_ctime; /* last change time */

    unsigned long  msg_lcbytes; /* Reuse junk fields for 32 bit */

    unsigned long  msg_lqbytes; /* ditto */

    unsigned short msg_cbytes; /* current number of bytes on queue */

    unsigned short msg_qnum; /* number of messages in queue */

    unsigned short msg_qbytes; /* max number of bytes on queue */

    __kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */

    __kernel_ipc_pid_t msg_lrpid; /* last receive pid */

    };

    相应函数

    int msgget(key_t key, int msgflg)  获取msg结构

    key 一个端口号或者由ftok获取

    msgflg :

    IPC_CREAT 不存在则创建,否则打开

    IPC_EXCL 不存在新建,否则返回错误 

    两个参数一起使用,那么.不存在则创建一个并打开,否则返回-1

    向队列发数据/获取数据

    ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

    int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

    msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可

    定义的通用结构,形态如下:

    struct msgstru{

    long mtype; //大大于0

    char mtext[用户指定大大小小];

    };

    msgtyp:从消息队列内读取的消息形态。如果值为零,则表示消息队列中的所有消息都会被读取。

    flag为0 时阻塞方式,IPC_NOWAIT非阻塞

    设置消息属性

    int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );

    IPC_STAT : 该命令用来获取消息队列对应的 msqid_ds 数据结构,并将其保存到 buf 指定的地址空间。

    IPC_SET : 该命令用用来设置消息队列的属性,要设置的属性存储在buf中。

    IPC_RMID : 从内核中删除 msqid 标识的消息队列。

    ftok函数  

    函数ftok把一个已存在的路径名和一个整数标识得转换成一个key_t值,称为IPC键:      

    key_t ftok(const char *pathname, int proj_id);

    该函数把从pathname导出的信息与id的低序8位组合成一个整数IPC键。

    信号量

    信号量的本质是数据操作锁,她本省不具有数据交换的功能,而是通过控制其他通信资源来实现进程间通信,他本身只是一种外部资源的标识.

    在这个过程中,信号量负责是数据操作的互斥,同步等功能

    当请求一个使用信号量来表示的资源时,进程需要先读取信号量的值来判断资源是否可用.

    大于0,资源可以请求,等于0,无资源可用,进程进入睡眠状态直到资源可用.

    当进程不再使用该资源时,信号量+1,对信号量的操作均为原子操作,

    信号量的工作原理

    P/V

    P:如果sv的值大于0,给他减一,;如果值为0 ,挂起该进程

    V:如果有其他进程因为等待该sv而挂起,就让他恢复运行,如果没有进程等待,那么sv+1

    相关文章

      网友评论

        本文标题:进程间通信

        本文链接:https://www.haomeiwen.com/subject/sjsusttx.html