概念: 进程彼此之间能够经过IPC消息进行通讯。进程产生的每条消息都被发送到一个IPC消息队列中,这条消息一直存放在队列中,直到另外一个进程将其读走为止。函数
优势:能够经过发送消息来几乎彻底避免命名管道的同步和阻塞问题;消息队列提供了一种从一个进程向另外一个进程发送一个数据块的方法。并且,每一个数据块被认为含有一个类型,接收进程能够独立地接收含有不一样类型值的数据块。spa
缺点:每一个数据块有一个最大长度的限制;系统中全部消息队列所包含的所有数据块的总长度也有一个上限。code
基本原理: 消息是由固定大小的首部和可变长度的正文组成的;可使用一个整数值标识消息,这就容许进程有选择的从消息队列中获取消息。只要进程从IPC消息队列中读出一条消息,内核就把这条消息删除;所以,一个进程只能接收一条给定的消息。当消息队列满时,则试图让新消息入队的进程可能被阻塞。当消息队列为空时,则接收进程甚至会被阻塞。blog
代码示例:队列
发送信息的程序的源文件msgsend.c的源代码为:进程
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/msg.h> #include <errno.h> #define MAX_TEXT 512 struct msg_st { long int msg_type; char text[MAX_TEXT]; }; int main() { int running = 1; 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 with error: %d\n", errno); exit(EXIT_FAILURE); } //向消息队列中写消息,直到写入end while(running) { //输入数据 printf("Enter some text: "); fgets(buffer, BUFSIZ, stdin); data.msg_type = 1; //注意2, 用来设置发送的信息的信息类型,即其发送的信息的类型为1 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) running = 0; sleep(1); } exit(EXIT_SUCCESS); }
接收信息的程序源文件为msgreceive.c的源代码为:get
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <sys/msg.h> struct msg_st { long int msg_type; char text[BUFSIZ]; }; int main() { int running = 1; int msgid = -1; struct msg_st data; long int msgtype = 0; //注意1,值为0表示获取队列中第一个可用的消息 //创建消息队列 msgid = msgget((key_t)1234, 0666 | IPC_CREAT); if(msgid == -1) { fprintf(stderr, "msgget failed with error: %d\n", errno); exit(EXIT_FAILURE); } //从队列中获取消息,直到遇到end消息为止 while(running) { if(msgrcv(msgid, (void*)&data, BUFSIZ, msgtype, 0) == -1) { fprintf(stderr, "msgrcv failed with errno: %d\n", errno); exit(EXIT_FAILURE); } printf("You wrote: %s\n",data.text); //遇到end结束 if(strncmp(data.text, "end", 3) == 0) running = 0; } //删除消息队列 if(msgctl(msgid, IPC_RMID, 0) == -1) { fprintf(stderr, "msgctl(IPC_RMID) failed\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
若是把注意1,即msgreceive.c文件main函数中的语句由long int msgtype = 0;改变为long int msgtype = 2;会发生什么状况,msgreceive将不能接收到程序msgsend发送的信息。由于在调用msgrcv函数时,若是msgtype(第四个参数)大于零,则将只获取具备相同消息类型的第一个消息,修改后获取的消息类型为2,而msgsend发送的消息类型为1,因此不能被msgreceive程序接收。
msgreceive若是没有接收到信息和输出,并且当msgsend输入end结束后,msgreceive也不会结束,经过jobs命令咱们能够看到它还在后台运行着。同步