1.消息队列的介绍
2.消息队列的系统调用
1)msgget
int msgget(key_t key, int msqflg);
msgget()创建或者获取一个消息队列
msgget()成功返回消息队列 ID,失败返回-1
msqflg: IPC_CREAT
2)msgsnd
int msgsnd(int msqid, const void *msqp, size_t msqsz, int msqflg);
msgsnd()发送一条消息;
//参数意义:
msqid:消息队列的id,因为系统中可能有多个消息队列,这id指明往哪个消息队列中添加数据;
msqp:往消息队列中添加的结构体,消息结构为:
struct msgbuf
{
long mtype; // 消息类型, 必须大于0(或者说>=1),长整型,比如图中的1,2
char mtext[1]; // 消息数据 ,用户自己定义,可以是任何类型;这里存放消息数据
};
msqsz: 指定 mtext 中有效数据的长度//注意仅仅只接收的数据的大小,不包含消息类型的大小;
msqflg:一般设置为 0 可以设置 IPC_NOWAIT//标志位,比如消息队列满了,是阻塞还是失败返回呢?给0代表消息满了自动阻塞,设置 IPC_NOWAIT意思是当整个消息队列满的时候会立即返回(no wait),返回一个失败而已
//返回值
msgsnd()成功返回 0, 失败返回-1
3)msgrcv
ssize_t msgrcv(int msqid, void *msgp, size_t msqsz, long msqtyp, int msqflg);
msgrcv()接收一条消息
msgrcv()成功返回 mtext 中接收到的数据长度, 失败返回-1,
msgp:接收消息的结构体,一般约定好,写入什么,接收什么结构体;
msqsz:接收消息的大小,大于等于发送的消息大小,一般和发送的消息大小一样.
msqtyp: 指定接收的消息类型(图中的1和2),类型可以为 0,为0表示不区分消息类型,按顺位接收消息;
msqflg: 一般设置为 0 可以设置 IPC_NOWAIT
//设置为IPC_NOWAIT,意思是当整个消息队列空的时候会立即返回(no wait),返回一个失败而已
//设置为0,意思是当整个消息队列空的时候会阻塞
4)msgctl
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msgctl()控制消息队列,也就是对消息队列做一个控制,可以设置消息队列,也可以移除消息队列;
msgctl()成功返回 0,失败返回-1
cmd: IPC_RMID
buf:设置或者获取消息队列需要的一个结构体,如果删除就直接给一个NULL;
//当创建一个消息队列的时候,只要不移除这个消息队列,它就会一直在,除非重启系统.
//或者人为删除:ipcrm -q id
3.消息队列的使用---代码演示
进程 a 发送一条消息,进程 b 读取消息。
//a.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <assert.h>
5 #include <string.h>
6 #include <sys/msg.h>
7
8 struct mess
9 {
10 long type;
11 char buff[128];
12 };
13
14 int main()
15 {
16 int msgid=msgget((key_t)1234,IPC_CREAT|0600);
17 assert(msgid!=-1);
18
19 struct mess dt;
20 dt.type=1;
21 strcpy(dt.buff,"hello1");
22
23 msgsnd(msgid,&dt,128,0);
24
25 exit(0);
26 }
//b.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <assert.h>
5 #include <string.h>
6 #include <sys/msg.h>
7
8 struct mess
9 {
10 long type;
11 char buff[128];
12 };
13
14 int main()
15 {
16 int msgid=msgget((key_t)1234,IPC_CREAT|0600);
17 assert(msgid!=-1);
18
19 struct mess dt;
20
21 msgrcv(msgid,&dt,128,1,0);
22 printf("read mess:%s\n",dt.buff);
23
24 exit(0);
25 }
演示发送消息,接收消息;
结论:
1).没有0号消息;0表示顺位接收;不管什么类型的消息都接收,因为没有0号消息,只有>=1的消息;
2).可以使用ipcrm 删除队列,也可以在程序中删除;
方法一:
ipcs -q /-m/-s 查看
ipcrm -q/m/s id 删除
方法二:
msgctl(msgid,IPC_RMID,NULL);
3).如果设置成IPC_NOWAIT,没有消息不等待
if(msgrcv(msgid,&dt,128,1,IPC_NOWAIT)==-1)//没有消息不等待,返回-1
24 {
25 printf("no mess\n");
26 }
27 else
28 {
29 printf("read:%s\n",dt.buff);
30 }
4).消息队列在内存中创建;