进程间通信4

时间:2021-08-04 08:43:00

消息队列的读写

写消息队列

  函数msgsnd用于向消息队列发送(写)数据.定义在头文件sys/msg.h中

int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int magflg);
msqid: 函数向msgid标识的消息队列发送了一个消息.
msgp:  msgp指向发送的消息.
msgsz: 要发送的消息的大小,不包含消息类型占用的4个字节.
magflg: 操作标志位.可以设置为0或IPC_NOWAIT.
     如果为0,则当消息队列已满的时候,msgsnd将会阻塞,直到消息可以写进消息队列. 如果为IPC_NOWAIT,当消息队列已满时,msgsnd函数将不等待立即返回.

  msgsnd函数成功返回0,失败返回-1.
  常见错误码:
    EAGAIN:  消息队列已满.
    EIDRM:  消息队列已被删除.
    EACCESS: 无权访问消息队列.

读消息队列

  读取消息的系统调用为msgrcv(),定义在头文件sys/msg.h中.

int msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long int msgtyp, int msgflg);

msqid: 消息队列描述符.
msgp: 读取的消息存储到msgp指向的消息结构中.
msgsz: 消息缓冲区的大小.
msgtyp: 为请求读取的消息类型.
msgflg: 操作标志位.

 msgflg可以为:
  IPC_NOWAIT: 若没有满足条件的消息,调用立即返回.
  IPC_EXCEPT: 与msgtyp配合使用,返回队列中第一个类型不为msgtyp的消息.
  IPC_NOERROR: 若队列中满足条件的消息内容大于所请求的msgsz字节,则把该消息截断,截断部分被丢弃.

获取和设置消息队列的属性

消息对列的属性保存在系统维护的数据结构msqid_ds中,可通过msgctl获取或设置消息队列的属性.msgctl定义在头文件sys/msg.h中.

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

msgctl系统调用对msqid标识的消息队列执行cmd操作.
 3种cmd操作:
  IPC_STAT: 获取消息队列对应的msqid_ds数据结构将其保存在buf指向的地址空间.
  IPC_SET: 设置消息队列的属性,要设置的属性存储在buf中.
  IPC_RMID: 从内核中删除msqid标识的消息队列.

消息队列与命名管道的比较

和命名管道一样,消息队列进行通信的进程可以是不相关的进程,同时它们都是通过发送和接收的方式来传递数据的。在命名管道中,发送数据用write,接收数据用read,则在消息队列中,发送数据用msgsnd,接收数据用msgrcv。而且它们对每个数据都有一个最大长度的限制。

消息队列的优势:
1、消息队列也可以独立于发送和接收进程而存在,从而消除了在同步命名管道的打开和关闭时可能产生的困难。
2、通过发送消息还可以避免命名管道的同步和阻塞问题,不需要由进程自己来提供同步方法。
3、接收程序可以通过消息类型有选择地接收数据,而不是像命名管道中那样,只能默认地接收。