消息队列,就是一些消息的列表,用户可以在消息队列中添加消息和读取消息等。消息队列用于运行于同一台机器上的进程间通信,与有名管道/FIFO很相似,但是它可以实现消息的随机查询,比有名管道有更大的优势。同时,消息队列以消息链表的形式存在于系统内核中,由"队列ID"来标识。我们可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向其中按照一定的规则添加新消息,对消息队列有读权限的进程则可以从消息队列中读走消息。
在Linux系统中消息队列的实现操作有:
① 创建或打开消息队列。使用的函数是msgget(),这里创建的消息队列的数量会受到系统消息队列数量的限制。
② 添加消息。使用的函数是msgsnd(),它把消息添加到已打开的消息队列末尾。
③ 读取消息。使用的函数是msgrcv(),它把消息从消息队列中取走,与管道不同的是,这里可以取走指定的某一条消息。
④ 控制消息队列。使用的函数是msgctl(),它可以完成多项功能。
1. 与消息队列相关的函数用法(1) msgget()函数功能:创建和访问一个消息队列,用法如下表所示。3. msgrcv()函数
功能:从一个消息队列获取消息,用法如下表所示。
#include #include struct msg_st { long int msg_type; char text[BUFSIZ];};int main(int argc, char **argv){ int msgid = -1; struct msg_st data; long int msgtype = 0; // 注意1 // 建立消息队列 msgid = msgget((key_t)1234, 0666 | IPC_CREAT); if (msgid == -1) { fprintf(stderr, "msgget failed width error: %d\n", errno); exit(EXIT_FAILURE); } // 从队列中获取消息,直到遇到end消息为止 while (1) { if (msgrcv(msgid, (void *)&data, BUFSIZ, msgtype, 0) == -1) { fprintf(stderr, "msgrcv failed width erro: %d", errno); } printf("You wrote: %s", data.text); // 遇到end结束 if (strncmp(data.text, "end", 3) == 0) { break; } } // 删除消息队列 if (msgctl(msgid, IPC_RMID, 0) == -1) { fprintf(stderr, "msgctl(IPC_RMID) failed\n"); } exit(EXIT_SUCCESS);}
msgsned.c源程序如下。#include #include #include #include #include #include #define MAX_TEXT 512struct msg_st { long int msg_type; char text[MAX_TEXT];};int main(int argc, char **argv){ struct msg_st data; char buffer[BUFSIZ]; int msgid = -1; // 建立消息队列 msgid = msgget((key_t)1234, 0666 | IPC_CREAT); if (msgid == -1) { fprintf(stderr, "msgget failed error: %d\n", errno); exit(EXIT_FAILURE); } // 向消息队里中写消息,直到写入end while (1) { printf("Enter some text: \n"); fgets(buffer, BUFSIZ, stdin); data.msg_type = 1; // 注意2 strcpy(data.text, buffer); // 向队列里发送数据 if (msgsnd(msgid, (void *)&data, MAX_TEXT, 0) == -1) { fprintf(stderr, "msgsnd failed\n"); exit(EXIT_FAILURE); } // 输入end结束输入 if (strncmp(buffer, "end", 3) == 0) { break; } sleep(1); } exit(EXIT_SUCCESS);}
编译运行,结果如下。