linux进程间通信-消息队列
2021-03-14
简介
消息队列是消息的链接表 ,存放在内核中并由消息队列标识符标识。我们将称消息队列为“队列”,其标识符为“队列ID”。 msgget
用于创建一个新队列或打开一个现存的队列。 msgsnd
用于将新消息添加到队列尾端。每个消息包含一个正长整型类型字段,一个非负长度以及实际数据字节(对应于长度),所有这些都在将消息添加到队列时,传送给msgsnd
。msgrcv
用于从队列中取消息。我们并不一定要以先进先出次序取消息,也可以按消息的类型字段取消息。
函数介绍
ftok
生成一个key(键值)
1
2
3
4
| #include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
|
- ftok根据路径名,提取文件信息,再根据这些文件信息及project ID合成key,该路径可以随便设置。
- 该路径是必须存在的,ftok只是根据文件inode在系统内的唯一性来取一个数值,和文件的权限无关。
- proj_id是可以根据自己的约定,随意设置。这个数字,有的称之为project ID; 在UNIX系统上,它的取值是1到255;
msgget
1
2
3
4
5
| #include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
|
功能:创建或取得一个消息队列对象
返回:消息队列对象的id 同一个key得到同一个对象
格式:msgget(key,flag|mode);
flag:可以是0或者IPC_CREAT(不存在就创建)
mode:同文件权限一样
msgsnd
将msgp消息写入标识为msgid的消息队列
1
| int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
|
- msgp
1
2
3
4
| struct msgbuf {
long mtype; /* message type, must be > 0 */消息的类型必须>0
char mtext[1]; /* message data */长度随意
};
|
- msgsz:要发送的消息的大小 不包括消息的类型占用的4个字节
- msgflg: 如果是0 当消息队列为满 msgsnd会阻塞,如果是IPC_NOWAIT 当消息队列为满时 不阻塞 立即返回
返回值:
msgrcv
从标识符为msgid的消息队列里接收一个指定类型的消息 并 存储于msgp中 读取后 把消息从消息队列中删除
1
2
| ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
|
参数:
- msgtyp:为 0 表示无论什么类型 都可以接收
- msgp:存放消息的结构体
- msgsz:要接收的消息的大小 不包含消息类型占用的4字节
- msgflg:如果是0 标识如果没有指定类型的消息 就一直等待,如果是IPC_NOWAIT 则表示不等待
msgctl
1
2
| int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msgctl(msgid,IPC_RMID,NULL);//删除消息队列对象
|
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| // snd.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <error.h>
#include <stdlib.h>
#include <fcntl.h>
typedef struct{
long type;
char name[20];
int age;
}Msg;
int main()
{
key_t key = ftok("./ftok_kk",'6');
printf("key:%x\n",key);
int msgid = msgget(key,IPC_CREAT|O_WRONLY|0777);
if(msgid<0)
{
perror("msgget error!");
exit(-1);
}
Msg m;
puts("please input your type name age:");
scanf("%ld%s%d",&m.type,m.name,&m.age);
msgsnd(msgid,&m,sizeof(m)-sizeof(m.type),0);
return 0;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| // rcv.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <error.h>
#include <stdlib.h>
#include <fcntl.h>
typedef struct{
long type;
char name[20];
int age;
}Msg;
int main()
{
key_t key = ftok("./ftok_kk",'6');
printf("key:%x\n",key);
int msgid = msgget(key,O_RDONLY);
if(msgid<0)
{
perror("msgget error!");
exit(-1);
}
Msg rcv;
long type;
puts("please input type you want!");
scanf("%ld",&type);
msgrcv(msgid,&rcv,sizeof(rcv)-sizeof(type),type,0);
printf("rcv--name:%s age:%d\n",rcv.name,rcv.age);
msgctl(msgid,IPC_RMID,NULL);
return 0;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
| $ ./snd
key:36012dbf
please input your type name age:
3
1
2
$ ./rcv
key:36012dbf
please input type you want!
3
rcv--name:1 age:2
|
其它
ipcs -q
查看消息队列
参考: https://www.cnblogs.com/liudw-0215/p/8978945.html