Linux IPC实践(5) --System V消息队列(2)

来源:互联网 发布:java停顿用法 编辑:程序博客网 时间:2024/05/16 10:07

消息发送/接收API

msgsnd函数

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);  

参数

   msgid: 由msgget函数返回的消息队列标识码, 也可以是通过ipcs命令查询出来的一个已经存在的消息队列的ID号

   msgp:是一个指针,指针指向准备发送的消息,

   msgsz:是msgp指向的消息长度, 注意:这个长度不含保存消息类型的那个long int长整型

   msgflg:控制着当前消息队列满到达系统上限时将要发生的事情,如果msgflg = IPC_NOWAIT表示队列满不等待,返回EAGAIN错误。

消息结构在两方面受到制约: (1)它必须小于系统规定的上限值(MSGMAX); (2)必须以一个long int长整数开始,接收者函数将利用这个长整数确定消息的类型;

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //消息结构参考形式如下:  
  2. struct msgbuf  
  3. {  
  4.     long mtype;       /* message type, must be > 0 */  
  5.     char mtext[1];    /* message data, 可以设定为更多的字节数 */  
  6. };  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /**示例1:  
  2. 测试1: 发送消息的最大长度为8192字节, 一旦超过这个值, 则msgsnd出错, 提示 Invalid argument错误; 
  3. 测试2: 消息队列所能够接收的最大字节数16384字节, 一旦超过这个长度, 如果msgflg为0(阻塞模式), 则进程会一直阻塞下去, 直到有进程来将消息取走; 而如果msgflg为IPC_NOWAIT模式, 则一个字节也不会写入消息队列, 直接出错返回; 
  4. **/  
  5. int main(int argc, char *argv[])  
  6. {  
  7.     if (argc != 3)  
  8.         err_quit("Usage: ./main <type> <length>");  
  9.   
  10.     int type = atoi(argv[1]);  
  11.     int len = atoi(argv[2]);  
  12.   
  13.     int msgid = msgget(0x255, 0666|IPC_CREAT);  
  14.     if (msgid == -1)  
  15.         err_exit("msgget error");  
  16.   
  17.     struct msgbuf *buf;  
  18.     buf = (struct msgbuf *)malloc(len + sizeof(msgbuf::mtype));  
  19.     buf->mtype = type;  
  20.     if (msgsnd(msgid, buf, len, IPC_NOWAIT) == -1)  
  21.         err_exit("msgsnd error");  
  22. }  

msgrcv函数

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);  

参数

   msgid: 由msgget函数返回的消息队列标识码

   msgp:是一个指针,指针指向准备接收的消息;

   msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个long int长整型

   msgtype:它可以实现接收优先级的简单形式(见下图)

   msgflg:控制着队列中没有相应类型的消息可供接收时将要发生的事(见下图)

返回值:

   成功->返回实际放到接收缓冲区里去的字节数(注意: 此处并不包含msgbuf中的mtype的长度[man-page: msgrcv() returns the number of bytes actually copied into the mtext array.]);

   失败->返回-1;

 

msgtyp参数

msgtyp=0

返回队列第一条信息

msgtyp>0

返回队列第一条类型等于msgtype的消息

msgtyp<0

返回队列第一条类型小于等于(<=)msgtype绝对值的消息,并且是满足条件的消息类型最小的消息(按照类型进行排序的顺序进行接收消息)

 

msgflg参数

msgflg=IPC_NOWAIT

队列没有可读消息不等待,返回ENOMSG错误。

msgflg=MSG_NOERROR

消息大小超过msgsz(msgrcv 函数的第三个参数)时被截断, 并且不会报错

msgtyp>0且msgflg=MSG_EXCEPT

接收类型不等于msgtype的第一条消息

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 示例2: 消息接收(配合示例1中程序使用) 
  2. 说明:     -t [number], 指定接收消息的类型, 类型为number的值 
  3. -n ,指定以IPC_NOWAIT模式接收消息 
  4. **/  
  5. int main(int argc, char *argv[])  
  6. {  
  7.     /** 解析参数 **/  
  8.     int type = 0;  
  9.     int flag = 0;  
  10.     int opt;  
  11.     while ((opt = getopt(argc, argv, "nt:")) != -1)  
  12.     {  
  13.         switch (opt)  
  14.         {  
  15.         case 'n':   // 指定IPC_NOWAIT选项  
  16.             flag |= IPC_NOWAIT;  
  17.             break;  
  18.         case 't':   // 指定接收的类型, 如果为0的话,说明是按照顺序接收  
  19.             type = atoi(optarg);  
  20.             break;  
  21.         default:  
  22.             exit(EXIT_FAILURE);  
  23.         }  
  24.     }  
  25.   
  26.     int msgid = msgget(0x255, 0);  
  27.     if (msgid == -1)  
  28.         err_exit("msgget error");  
  29.   
  30.     const int MSGMAX = 8192;    //指定一条消息的最大长度  
  31.     struct msgbuf *buf;  
  32.     buf = (struct msgbuf *)malloc(MSGMAX + sizeof(buf->mtype));  
  33.   
  34.     ssize_t nrcv;  
  35.     if ((nrcv = msgrcv(msgid, buf, MSGMAX, type, flag)) == -1)  
  36.         err_exit("msgrcv error");  
  37.     cout << "recv " << nrcv << " bytes, type = " << buf->mtype << endl;  
  38. }  

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 综合示例: msgsnd/msgrcv, 消息发送/接收实践 **/  
  2. //1. 消息发送  
  3. int main()  
  4. {  
  5.     int msgid = msgget(0x1234,0666|IPC_CREAT);  
  6.     if (msgid == -1)  
  7.         err_exit("msgget error");  
  8.   
  9.     struct msgBuf myBuffer;  
  10.     for (int i = 0; i < 128; ++i)  
  11.     {  
  12.         myBuffer.mtype = i+1;  
  13.         sprintf(myBuffer.mtext,"Hello, My number is %d",i+1);  
  14.         if (msgsnd(msgid,&myBuffer,strlen(myBuffer.mtext),IPC_NOWAIT) == -1)  
  15.             err_exit("msgsnd error");  
  16.     }  
  17. }  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //2. 消息接收:从队首不断的取数据  
  2. int main(int argc, char *argv[])  
  3. {  
  4.     int msgid = msgget(0x1234, 0);  
  5.     if (msgid == -1)  
  6.         err_exit("msgget error");  
  7.   
  8.     struct msgBuf buf;  
  9.     ssize_t nrcv;  
  10.     while ((nrcv = msgrcv(msgid, &buf, sizeof(buf.mtext), 0, IPC_NOWAIT)) > 0)  
  11.     {  
  12.         cout << "recv " << nrcv << " bytes, type: " << buf.mtype  
  13.         << ", message: " << buf.mtext << endl;  
  14.     }  
  15. }  

[附]-getopt函数的用法

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <unistd.h>  
  2. int getopt(int argc, char * const argv[],  
  3.                   const char *optstring);  
  4.   
  5. extern char *optarg;  
  6. extern int optind, opterr, optopt;  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //示例: 解析 ./main -n -t 3 中的参数选项  
  2. int main(int argc, char *argv[])  
  3. {  
  4.     while (true)  
  5.     {  
  6.         int opt = getopt(argc, argv, "nt:");  
  7.         if (opt == '?')  
  8.             exit(EXIT_FAILURE);  
  9.         else if (opt == -1)  
  10.             break;  
  11.   
  12.         switch (opt)  
  13.         {  
  14.         case 'n':  
  15.             cout << "-n" << endl;  
  16.             break;  
  17.         case 't':  
  18.             int n = atoi(optarg);  
  19.             cout << "-t " << n << endl;  
  20.             break;  
  21.         }  
  22.     }  
  23. }  
0 0
原创粉丝点击