System V消息队列(2)

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

msgrcv函数

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

参数

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

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

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

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

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

返回值:

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

失败->返回-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的第一条消息

/** 示例2: 消息接收(配合示例1中程序使用)说明: -t [number], 指定接收消息的类型, 类型为number的值-n ,指定以IPC_NOWAIT模式接收消息**/int main(int argc, char *argv[]){/** 解析参数 **/int type = 0;int flag = 0;int opt;while ((opt = getopt(argc, argv, "nt:")) != -1){switch (opt){case ‘n’: // 指定IPC_NOWAIT选项flag |= IPC_NOWAIT;break;case ‘t’: // 指定接收的类型, 如果为0的话,说明是按照顺序接收type = atoi(optarg);break;default:exit(EXIT_FAILURE);}}int msgid = msgget(0x255, 0);if (msgid == -1)err_exit("msgget error");const int MSGMAX = 8192; //指定一条消息的最大长度struct msgbuf *buf;buf = (struct msgbuf *)malloc(MSGMAX + sizeof(buf->mtype));ssize_t nrcv;if ((nrcv = msgrcv(msgid, buf, MSGMAX, type, flag)) == -1)err_exit("msgrcv error");cout << "recv " << nrcv << " bytes, type = " << buf->mtype << endl;}/** 综合示例: msgsnd/msgrcv, 消息发送/接收实践 **///1. 消息发送int main(){int msgid = msgget(0x1234,0666|IPC_CREAT);if (msgid == -1)err_exit("msgget error");struct msgBuf myBuffer;for (int i = 0; i < 128; ++i){myBuffer.mtype = i+1;sprintf(myBuffer.mtext,"Hello, My number is %d",i+1);if (msgsnd(msgid,&myBuffer,strlen(myBuffer.mtext),IPC_NOWAIT) == -1)err_exit("msgsnd error");}}//2. 消息接收:从队首不断的取数据int main(int argc, char *argv[]){int msgid = msgget(0x1234, 0);if (msgid == -1)err_exit("msgget error");struct msgBuf buf;ssize_t nrcv;while ((nrcv = msgrcv(msgid, &buf, sizeof(buf.mtext), 0, IPC_NOWAIT)) > 0){cout << "recv " << nrcv << " bytes, type: " << buf.mtype<< ", message: " << buf.mtext << endl;}}

[附]-getopt函数的用法

#include <unistd.h>int getopt(int argc, char * const argv[],const char *optstring);extern char *optarg;extern int optind, opterr, optopt;//示例: 解析 ./main -n -t 3 中的参数选项int main(int argc, char *argv[]){while (true){int opt = getopt(argc, argv, "nt:");if (opt == ‘?’)exit(EXIT_FAILURE);else if (opt == -1)break;switch (opt){case ‘n’:cout << "-n" << endl;break;case ‘t’:int n = atoi(optarg);cout << "-t " << n << endl;break;}}}

,经验是由痛苦中粹取出来的

System V消息队列(2)

相关文章:

你感兴趣的文章:

标签云: