【详解】进程间通信之消息队列

消息队列:

操作系统在内核中创建一个队列,使得用户进程可以一个放数据,一个取数据,消息队列中的每个节点存放的信息有:消息类型号、消息的长度、消息的具体内容,具体情况如图:

所引用的头文件:

#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

猜你喜欢

转载自blog.csdn.net/enjoymyselflzz/article/details/81569044