Linux 进程通信—消息队列

  消息队列就是一个消息的链表。可以把消息看做一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向中按照一定的规则添加新信息,对消息队列有读权限的进程可以从消息队列中读走消息,消息队列是随内核持续的。

消息队列就是一个消息的链表。每个消息队列都有一个队列头,用结构struct msg_queue来描述。队列头中包含了该消息队列的大量信息,包括消息队列键值,用户ID,组ID,消息队列中消息数目等,甚至记录了最近对消息队列读写进程的ID。读者可以访问这些信息,也可以设置其中的某些信息。

  全局数据结构struct ipc_ids msg_ids可以访问到每个消息队列头的第一个成员struct kern_ipc_perm能够与具体的消息队列对应起来是因为在该结构中,有一个key_t类型成员key,而key则确定一个消息队列。

  消息队列的操作有以下三种类型。

  1.打开或者创建消息队列

  2.读写操作

  3.获得或者设置消息队列属性。

  消息队列的API函数

  ftok函数:

  作用:将文件名转化为键值

  函数原型:key_t fotk(char *pathname ,char proj)

  返回值:返回与文件对应的键值

  2.msgget函数

  作用:创建消息队列

  原型:int msgget(key_t key,int msgflg)

  参数:键值和权限,是可读还是可写,IPC_PRIVATE,设定一个数字,也可以由tok函数获得

  返回值:成功则是消息队列的id,出错-1

  包含的头文件:#include <sys/types.h>

                              #include <sys/ipc.h>

                              #include <sys/shm.h>

  3.msgsnd函数

  作用:写数据到消息队列

  原型:int msgsnd(int msgid,const void * msggp,size_t msgsize,int msgflg)

  参数:msggp:消息结构

              struct msgbuf{

              long msgtype;

              char mtext[1]

}

  msgsize:消息的字节数

  msgflg:IPC_NOWAIT写不进去消息直接返回

  0一直等待到能写进去消息为止

  返回值:成功为0

                  出错为-1;

  包含的头文件:#include <sys/types.h>

                              #include <sys/ipc.h>

                              #include <sys/msg.h>

  4.msgrcv函数

  作用:用于读出消息队列的数据

  原型:int msgrcv(int msqid,struct msgbuf*msgp,int msgsz,long msgtyp,int msgflg)

  返回值:成功返回读出消息的实际字节数,出错-1.


  5.msgctl函数

  作用:用于控制消息队列

  原型:int msgctl(int msqid,int cmd,struct msqid_ds*buf);

  该系统调用对由msqid标识的消息队列执行cmd操作,共有三种操作:IPC_STAT,IPC_SET,IPC_RMID

  IPC_STAT:用来获取消息队列信息,返回的信息存储在buf指向的msqid结构中。

  IPC_SET:用来设置消息队列的属性

  IPC_RMID:删除msqd标识的消息队列

  返回值:成功为0,否则返回-1。


  每个消息队列的容量都有限制,该值因为系统不同而不同。另一个限制是每个消息队列所能容纳的最大消息数。

  以下为应用实例

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <stdlib.h>  
  2. #include <stdio.h>  
  3. #include <string.h>  
  4. #include <errno.h>  
  5. #include <unistd.h>  
  6.   
  7. #include <sys/types.h>  
  8. #include <sys/ipc.h>  
  9. #include <sys/msg.h>  
  10.   
  11. struct my_msg_st  
  12. {  
  13.     long int my_msg_type;  
  14.     char some_text[BUFSIZ];  
  15. };  
  16.   
  17. int main(void)  
  18. {  
  19.     int running=1;  
  20.     int msgid;  
  21.     struct my_msg_st some_data;  
  22.     long int msg_to_receive=0;  
  23.   
  24.     /*创建消息队列*/  
  25.     msgid=msgget((key_t)1234,0666 | IPC_CREAT);  
  26.     if(msgid==-1)  
  27.     {  
  28.         fprintf(stderr,"msgget failed with error: %d\n",errno);  
  29.         exit(EXIT_FAILURE);  
  30.     }  
  31.       
  32.     /*循环从消息队列中接收消息*/  
  33.     while(running)  
  34.     {  
  35.         /*读取消息*/  
  36.         if(msgrcv(msgid,(voidvoid *)&some_data,BUFSIZ,msg_to_receive,0)==-1)  
  37.         {  
  38.             fprintf(stderr,"msgrcv failed with error: %d\n",errno);  
  39.             exit(EXIT_FAILURE);  
  40.         }  
  41.   
  42.         printf("You wrote: %s",some_data.some_text);  
  43.   
  44.         /*接收到的消息为“end”时结束循环*/  
  45.         if(strncmp(some_data.some_text,"end",3)==0)  
  46.         {  
  47.             running=0;  
  48.         }  
  49.     }  
  50.   
  51.     /*从系统内核中移走消息队列*/  
  52.     if(msgctl(msgid,IPC_RMID,0)==-1)  
  53.     {  
  54.         fprintf(stderr,"msgctl(IPC_RMID) failed\n");  
  55.         exit(EXIT_FAILURE);  
  56.     }  
  57.     exit(EXIT_SUCCESS);  
  58. }  

上面为读取的程序,开启一个中断,./read。

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <stdlib.h>  
  2. #include <stdio.h>  
  3. #include <string.h>  
  4. #include <errno.h>  
  5. #include <unistd.h>  
  6. #include <sys/types.h>  
  7. #include <sys/ipc.h>  
  8. #include <sys/msg.h>  
  9. #define MAX_TEXT 512  
  10.   
  11.   
  12. struct my_msg_st  
  13. {  
  14.     long int my_msg_type;  
  15.     char some_text[MAX_TEXT];  
  16. };  
  17.   
  18.   
  19. int main(void)  
  20. {  
  21.     int running=1;  
  22.     struct my_msg_st some_data;  
  23.     int msgid;  
  24.     char buffer[BUFSIZ];  
  25.   
  26.   
  27.     /*创建消息队列*/  
  28.     msgid=msgget((key_t)1234,0666 | IPC_CREAT);  
  29.     if(msgid==-1)  
  30.     {  
  31.         fprintf(stderr,"msgget failed with error:%d\n",errno);  
  32.         exit(EXIT_FAILURE);  
  33.     }  
  34.   
  35.   
  36.     /*循环向消息队列中添加消息*/  
  37.     while(running)  
  38.     {  
  39.         printf("Enter some text:");  
  40.         fgets(buffer,BUFSIZ,stdin);  
  41.         some_data.my_msg_type=1;  
  42.         strcpy(some_data.some_text,buffer);  
  43.   
  44.   
  45.         /*添加消息*/  
  46.         if(msgsnd(msgid,(voidvoid *)&some_data,MAX_TEXT,0)==-1)  
  47.         {  
  48.             fprintf(stderr,"msgsed failed\n");  
  49.             exit(EXIT_FAILURE);  
  50.         }  
  51.   
  52.   
  53.         /*用户输入的为“end”时结束循环*/  
  54.         if(strncmp(buffer,"end",3)==0)  
  55.         {  
  56.             running=0;  
  57.         }  
  58.     }  
  59.     exit(EXIT_SUCCESS);  
  60. }  
  61.    

这是write的程序,在另外一个终端开启。

之后就可以实现在消息队列中读写。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值