Linux进程通信之System V消息队列

发表于:2014-7-01 09:37

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:anonymalias    来源:51Testing软件测试网采编

  key:消息队列的键,用来创建一个消息队列。System IPC都有一个key,作为IPC的外部标识符,创建成功后返回的描述符作为IPC的内部标识符使用。key的主要目的就是使不同进程在同一IPC汇合。key具体说可以有三种方式生成:
  不同的进程约定好的一个值;
  通过相同的路径名和项目ID,调用ftok()函数,生成一个键;
  还可以设置为IPC_PRIVATE,这样就会创建一个新的,唯一的IPC对象;然后将返回的描述符通过某种方式传递给其他进程;
  oflg:指定创建或打开消息队列的标志和读写权限(ipc_perm中的mode成员)。我们知道System V IPC定义了自己的操作标志和权限设置标志,而且都是通过该参数传递,这和open函数存在差别,open函数第三个参数mode用于传递文件的权限标志。System V IPC的操作标志包含:IPC_CREAT,IPC_EXCL,权限设置标志如下图:
  下面是创建消息队列的测试代码:
#include <iostream>
#include <cstring>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/msg.h>
using namespace std;
#define  PATH_NAME "/tmp/anonymQueue"
int main(int argc, char **argv)
{
key_t key;
int fd;
if ((fd = open(PATH_NAME, O_CREAT, 0666)) < 0)
{
cout<<"open file "<<PATH_NAME<<"failed.";
cout<<strerror(errno)<<endl;
return -1;
}
close(fd);
key = ftok(PATH_NAME, 0);
int msgID;
if ((msgID = msgget(key, IPC_CREAT | 0666)) < 0)
{
cout<<"open message queue failed...";
cout<<strerror(errno)<<endl;
return -1;
}
cout<<"key:0x"<<hex<<key<<endl;
cout<<"descriptor id:"<<dec<<msgID<<endl;
}
  在Linux 2.6.18下运行结果:
  key:0x8015
  descriptor id:917511
  实现System V IPC的任何系统都提供两个特殊的程序ipcs和ipcrm。ipcs输出IPC的各种信息,ipcrm则用于删除各种System V IPC。由于System V IPC不属于POSIX标准,所以这两个命令也未被标准化。下面是通过ipcs命令来查看刚刚创建的消息队列。
  [root@idcserver program]# ipcs -q -i 917511
  Message Queue msqid=917511
  uid=0   gid=0   cuid=0  cgid=0  mode=0666
  cbytes=0        qbytes=65536    qnum=0  lspid=0 lrpid=0
  send_time=Not set
  rcv_time=Not set
  change_time=Wed Aug  7 16:39:46 2013
  2 System V消息队列的使用
  System V消息队列的写入消息使用下面的函数接口:
  #include <sys/msg.h>
  int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
  //成功返回0,失败返回-1
  msqid:消息队列的描述符;
  msgp:指向存放消息的缓冲区,该缓冲区中包含消息类型和消息体两部分内容。该缓冲区的结构是由用户定义的,在<sys/msg.h>中有关于该缓冲区结构定义的参版考模:
  struct msgbuf
  {
  long int mtype;             /* type of received/sent message */
  char mtext[1];              /* text of the message */
  };
  缓冲区的开头是一个long型的消息类型,该消息类型必须是一个非负数。紧跟在消息类型后面的是消息体部分(如果消息长度大于0),参考模版中定义的mtext只是说明消息体,该部分可以自定义长度。我们自己的应用都会定义特定的消息结构。
  msgsz:缓冲区中消息体部分的长度;
  msgflg:设置操作标志。可以为0,IPC_NOWAIT;用于在消息队列中没有可用的空间时,调用线程采用何种操作方式。
  标志为IPC_NOWAIT,表示msgsnd操作以非阻塞的方式进行,在消息队列中没有可用的空间时,msgsnd操作会立刻返回。并指定EAGAIN错误;
  标志为0,表示msgsnd操作以阻塞的方式进行,这种情况下在消息队列中没有可用的空间时调用线程会被阻塞,直到下面的情况发生:
  等到有存放消息的空间;
  消息队列从系统中删除,这种情况下回返回一个EIDRM错误;
  调用线程被某个捕捉到的信号中断,这种情况下返回一个EINTR错误;
  System V消息队列的读取消息使用下面的函数接口:
  #include <sys/msg.h>
  ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
  //成功返回接收到的消息的消息体的字节数,失败返回-1
  msqid:消息队列的描述符;
  msgp:指向待存放消息的缓冲区,该缓冲区中将会存放接收到的消息的消息类型和消息体两部分内容。该缓冲区的结构是由用户定义的,和msgsnd相对应。
  msgsz:缓冲区中能存放消息体部分的最大长度,这也是该函数能返回的最大数据量;该字段的大小应该是sizeof(msg buffer) - sizeof(long);
  msgtyp:希望从消息队列中获取的消息类型。
  msgtyp为0,返回消息队列中的第一个消息;
  msgtyp > 0,返回该消息类型的第一个消息;
  msgtyp < 0,返回小于或等于msgtyp绝对值的消息中类型最小的第一个消息;
  msgflg:设置操作标志。可以为0,IPC_NOWAIT,MSG_NOERROR;用于在消息队列中没有可用的指定消息时,调用线程采用何种操作方式。
  标志为IPC_NOWAIT,表示msgrcv操作以非阻塞的方式进行,在消息队列中没有可用的指定消息时,msgrcv操作会立刻返回,并设定errno为ENOMSG。
  标志为0,表示msgrcv操作是阻塞操作,直到下面的情况发生:
  消息队列中有一个所请求的消息类型可以获取;
  消息队列从系统中删除,这种情况下回返回一个EIDRM错误;
  调用线程被某个捕捉到的信号中断,这种情况下返回一个EINTR错误;
  标志为MSG_NOERROR,表示接收到的消息的消息体的长度大于msgsz长度时,msgrcv采取的操作。如果设置了该标志msgrcv在这种情况下回截断数据部分,而不返回错误,否则返回一个E2BIG错误。
42/4<1234>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号