Linux进程间的通信方式----消息队列

本文详细介绍了消息队列的基本概念、工作原理及核心API,包括创建、读写消息队列的操作,以及通过示例展示了如何使用消息队列进行进程间通信。

1. 消息队列就是一个消息的链表。可以把消息看做一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向中按照一定的规则添加新信息,对消息队列有读权限的进程可以从消息队列中读走消息,消息队列是随内核持续的。每个消息队列都有一个队列头,用结构struct msg_queue来描述。队列头中包含了该消息队列的大量信息,包括消息队列键值,用户ID,组ID,消息队列中消息数目等,甚至记录了最近对消息队列读写进程的ID。读者可以访问这些信息,也可以设置其中的某些信息。

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

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

    a. 打开或者创建消息队列
    b. 读写操作

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

4.键值的概念:消息队列的内核持续性要求每个消息队列在系统范围内都有对应的唯一的键值,要获得一个消息队列的描述字,必须提供该消息队列的键值

5.ftok函数:

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

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

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

6.msgget函数

  作用:创建消息队列

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

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

                    msgflg:IPC_CREAT:无消息队列时创建消息队列

                                IPC_EXCL:只有在消息队列不存在时创建消息队列,否则报错

                                IPC_NOWAIT:读写消息队列无法得到满足时不等待,之间返

  返回值:执行成功时,返回与键值key对应的消息队列描述字;执行出错,返回-1

7.msgrcv函数

函数的原型:int msgrcv(int msqid, void *msgp, size_t msgsz, long int msgtyp, int msgflg);

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

              #include<sys/ipc.h>

              #include<sys/msg.h>

参数:

msqid:消息队列的ID(描述字)

msgp:消息读取后存放的内存空间首地址,是消息结构类型的指针

msgsz:消息数据的长度

msgtyp:请求读取的消息类型(正整数)

msgflg:接收标志

IPC_NOWAIT:读不到数据时直接返回,不等待

   0:一直等待到成功读取数据

返回值:执行成功,返回0;执行出错,返回-1

8.msgsnd函数

函数的原型:int msgsnd(int msqid, struct msgbuf *msgp, int msgsz,int msgflg);

头文件:

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/msg.h>

参数:

① msqid:已打开的消息队列ID(描述字)

② msgp:指向消息结构的指针,结构如下:

struct msgbuf

{

long mtype; //消息类型,大于0

char mtext[1]; //消息数据的首地址

};

③ msgsz:消息数据的长度

④ msgflg:发送标志

   IPC_NOWAIT:写不进数据时直接返回,不等待

   0:一直等待到成功写入数据

返回值:执行成功,返回0;执行出错,返回-1

 

(4)控制消息队列

通常在使用完消息队列后用msgctl函数删除消息队列

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

头文件:

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/msg.h>

参数:

① msqid:消息队列的ID(描述字)

② cmd:相应的命令

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

IPC_SET:设置消息队列的属性

IPC_RMID:删除消息队列

③ buf:消息队列的结构类型变量

返回值:执行成功,返回0;执行出错,返回-1


例:

读取函数:

[plain]  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. }  


发送函数:
[plain]  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. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值