linux 消息队列
场景:linux过程通信之消息队列
linux进程通信之消息队列
(1)、定义:
消息队列就是一个消息链表。可以把消息看作一个记录,具有特定格式。许多方式看来,消息队列类似于有名管道,但是却没有与打开与关闭管道的复杂关联。
1、POSIX消息队列;2、系统V消息队列;
POSIX-----可移植的操作系统接口;
(3)、删除消息队列:
1、内核重启;2、人工删除;
(4)、键值:
每一个消息队列在系统范围内有唯一的键值,所以需要获得一个消息队列的描述字,则需要键值;
key_t ftok(char* pathname,char proj) //file to key
功能:返回文件名对应的键值;
pathname:文件名;
proj:项目名;
(5)、获取消息队列描述字:
int msgget(key_t key,int msgflg);
key:键值,有ftok产生;
msgflg:标志位;1、IPC_CREAT: 创建新的消息队列;
2、IPC_EXCL: 如果创建的消息队列已存在,则返回错误;
3、IPC_NOWAIT:不阻塞;
(6)、消息队列格式:
struct msgbuf
{
long mtype; //消息类型
char mtext[1]; //消息数据首地址
}
(7)、发送消息:
int msgsnd(int msqid,struct msgbuf* msgp,int smgsz,int msgflg);
msgqid:已打开的消息队列ID;
msgp: 存放消息的结构;
msgsz: 消息数据长度;
msgflg: 发送标志;
(8)、接收消息:
int msgrcv(int msqid,struct msgbuf * msgp,int msgsz,long msgtyp,int msgflg);
写进程代码:创建或打开一个消息队列,把消息写入消息队列直至遇到字符串“end”。
测试结果:
linux进程通信之消息队列
(1)、定义:
消息队列就是一个消息链表。可以把消息看作一个记录,具有特定格式。许多方式看来,消息队列类似于有名管道,但是却没有与打开与关闭管道的复杂关联。
消息队列提供了一种在两个不相关的进程之间传递数据的简单高效的方法。与有名管道比起来,消息队列的有点在于独立于发送与接收进程,这减少了在打开与关闭有名管道之间同步的困难。
(2)、分类:1、POSIX消息队列;2、系统V消息队列;
POSIX-----可移植的操作系统接口;
(3)、删除消息队列:
1、内核重启;2、人工删除;
(4)、键值:
每一个消息队列在系统范围内有唯一的键值,所以需要获得一个消息队列的描述字,则需要键值;
key_t ftok(char* pathname,char proj) //file to key
功能:返回文件名对应的键值;
pathname:文件名;
proj:项目名;
(5)、获取消息队列描述字:
int msgget(key_t key,int msgflg);
key:键值,有ftok产生;
msgflg:标志位;1、IPC_CREAT: 创建新的消息队列;
2、IPC_EXCL: 如果创建的消息队列已存在,则返回错误;
3、IPC_NOWAIT:不阻塞;
(6)、消息队列格式:
struct msgbuf
{
long mtype; //消息类型
char mtext[1]; //消息数据首地址
}
(7)、发送消息:
int msgsnd(int msqid,struct msgbuf* msgp,int smgsz,int msgflg);
msgqid:已打开的消息队列ID;
msgp: 存放消息的结构;
msgsz: 消息数据长度;
msgflg: 发送标志;
(8)、接收消息:
int msgrcv(int msqid,struct msgbuf * msgp,int msgsz,long msgtyp,int msgflg);
功能:从msqid代表的消息队列中读取一个msgtyp类型的消息,并把消息存储在msgp指向的msgbuf结构中;
示例代码, 创建一个消息队列,使两个进程能够通过它实现数据通讯。
读进程代码:创建或打开一个消息队列,并从消息队列中读出消息直至遇到字符串“end”。
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> struct my_msg_st { long int my_msg_type; char some_text[BUFSIZ]; }; /* * 程序入口 * */ int main(void) { int running=1; int msgid; struct my_msg_st some_data; long int msg_to_receive=0; /*创建消息队列*/ msgid=msgget((key_t)1234,0666 | IPC_CREAT); if(msgid==-1) { fprintf(stderr,"msgget failed with error: %d\n",errno); exit(EXIT_FAILURE); } /*循环从消息队列中接收消息*/ while(running) { /*读取消息*/ if(msgrcv(msgid,(void *)&some_data,BUFSIZ,msg_to_receive,0)==-1) { fprintf(stderr,"msgrcv failed with error: %d\n",errno); exit(EXIT_FAILURE); } printf("You wrote: %s",some_data.some_text); /*接收到的消息为“end”时结束循环*/ if(strncmp(some_data.some_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); }
写进程代码:创建或打开一个消息队列,把消息写入消息队列直至遇到字符串“end”。
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #define MAX_TEXT 512 struct my_msg_st { long int my_msg_type; char some_text[MAX_TEXT]; }; /* * 程序入口 * */ int main(void) { int running=1; struct my_msg_st some_data; int msgid; char buffer[BUFSIZ]; /*创建消息队列*/ msgid=msgget((key_t)1234,0666 | IPC_CREAT); if(msgid==-1) { fprintf(stderr,"msgget failed with error:%d\n",errno); exit(EXIT_FAILURE); } /*循环向消息队列中添加消息*/ while(running) { printf("Enter some text:"); fgets(buffer,BUFSIZ,stdin); some_data.my_msg_type=1; strcpy(some_data.some_text,buffer); /*添加消息*/ if(msgsnd(msgid,(void *)&some_data,MAX_TEXT,0)==-1) { fprintf(stderr,"msgsed failed\n"); exit(EXIT_FAILURE); } /*用户输入的为“end”时结束循环*/ if(strncmp(buffer,"end",3)==0) { running=0; } } exit(EXIT_SUCCESS); }
测试结果: