消息队列:
操作系统在内核中创建一个队列,使得用户进程可以一个放数据,一个取数据,消息队列中的每个节点存放的信息有:消息类型号、消息的长度、消息的具体内容,具体情况如图:
所引用的头文件:
#include<sys.msg.h>
#include<sys/ipc.h>
打开或者创建一个消息队列:
msgget(key_t key,int flags)
内核对象没有文件名这一说,它用key来代表,用flags来赋予权限
flags:IPC_CREAT|0644 :创建并赋予权限
打开用0就可以
返回值为消息队列的id,相当于open打开文件的文件描述符。
具体代码:
1 #include<sys/ipc.h>
2 #include<stdio.h>
3 #include<sys/msg.h>
4 #include<stdlib.h>
5
6 int main()
7 {
8 int msgid= msgget(12,IPC_CREAT|0644);
9 if(msgid==-1)
10 {
11 perror("msgget");
12 exit(1);
13 }
14 else
15 {
16 printf("msg creat success");
17 }
18
19 }
往消息队列中放数据:
msgsnd(int id,const void *msgp,size_t len,int flag)
id为msgget的返回值,即已打开的消息队列
msgp所要发送消息的位置
len:消息的字节数,不包括channel的大小
flag:0 达到上限等待取走后再放入
失败返回-1,成功返回0
struct msgbuf{
long channel; //消息类型,必须>=1
char mtext[ ];//写上自己消息的内容。
};
atoi 把字符串转化成整形数
具体代码:
1 #include<stdio.h>
2 #include<string.h>
3 #include<sys/msg.h>
4 #include<sys/ipc.h>
5 #include<stdlib.h>
6 struct msgbuf{
7 long mtype;
8 char mtext[100];
9 };
10 int main(int argc,char *argv[])
11 {
12 if(argc!=2)
13 {
14 fprintf(stderr,"usage:%s type\n",argv[0]);
15 exit(1);
16 }
17 int id=msgget(12,0);
18 if(id==-1)
19 {
20 perror("msgget");
21 exit(1);
22 }
23 struct msgbuf mb;
24 memset(&mb,0x00,sizeof(mb));
25 mb.mtype=atoi(argv[1]);
26 printf("msg:");
27 fgets(mb.mtext,99,stdin);
28 int r=msgsnd(id,&mb,strlen(mb.mtext),0);
29 if(r==-1)
30 {
31 perror("msgsnd");
32 exit(1);
33 }
34 }
从消息队列取数据
msgrcv(int id,const void *msgp,size_t len,long msgtype,int flag)
调用一次获取一个数据,如果类型号相同,则取第一个入队的数据
id:已打开的消息队列
msgp:消息存放的位置
len:不包括消息类型的大小,只是装数据的大小
msgtype:获取消息类型为几的参数
flag:0
失败返回-1,成功返回实际读取的字节数
具体代码:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<sys/msg.h>
5 #include<sys/ipc.h>
6 struct msgbuf{
7 long mtype;
8 char mtext[100];
9 };
10 int main(int argc,char* argv[])
11 {
12 if(argc!=2)
13 {
14 fprintf(stderr,"usage:%s type\n",argv[0]);
15 exit(1);
16 }
17 int id=msgget(12,0);
18 if(id==-1)
19 {
20 perror("msgget");
21 exit(1);
22 }
23 struct msgbuf mb;
24 memset(&mb,0x00,sizeof(mb));
25 if(msgrcv(id,&mb,100,atoi(argv[1]),0)==-1)
26 {
27 perror("msgrcv");
28 exit(1);
29 }
30 printf("msg:%s\n",mb.mtext);
31 }
销毁消息队列:
int msgctl(int id, int cmd, struct msqid_ds *buf);
id:已打开的消息队列
cmd:命令,我们通常选用IPC_RMID 关闭消息队列
buf:NULL
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<sys/ipc.h>
4 #include<sys/msg.h>
5 int main()
6 {
7 int id=msgget(12,0);
8 msgctl(id,IPC_RMID,NULL);
9 }
补充说明:
用ipcs可以查看ipc对象(共享内存、消息队列、信号量全部都会显示出来)
ipcs -q 只查看消息队列
ipcrm -Q key 删除指定IPC对象的消息队列
这里我们以创建、删除为例示范:
系统中最多可以创建多少个消息队列?
用cat/proc/sys/kernel/msgmni可以查看
一条消息最多能装多少个字节?
cat/proc/sys/kernel/msgmax
一个消息队列中所有消息的总字节数为多少?
cat/proc/sys/kernel/msgnb