Linux进程通信之消息队列

来源:互联网 发布:小米4能用移动4g网络吗 编辑:程序博客网 时间:2024/05/19 17:47

Linux进程通信之消息队列

        消息队列就是一个消息的链表,我们可以把消息看作一个记录,具有特定的格式。消息队列也是进程中通信常见的方式之一,进程可以向消息队列中按照一定的规则添加新消息;另一些进程则可以从消息队列中读走消息。下面我们就来看看常见的消息队列函数:

(1)   创建或打开一个消息队列

int msgget(key_t key , intflag);

消息队列的通信编程与我前面学的信号量、共享内存差不多,都属于IPC结构,我们创建一个消息队列其实也就是创建一个消息队列的标识符。msgget的两个参数应该是非常清楚的,因为在我们的共享内存和信号量都会用到这两个参数,第一个就是我们的键值,用于产生我们的标识符,第二个参数是一个标志,指定消息队列的属性和权限。

该函数成功执行后就返回消息队列ID,以后我们就可以根据这个ID来访问这个消息队列。

(2)   将数据放到消息队列中

int msgsnd(int mspid , const void *ptr, size_t  nbytes , int flag);

这个函数的参数有点多,我们来一一介绍一下

mspid:这个参数就是我们前面用msgget函数返回的消息队列的ID。

prt: prt参数指向一个准备发送消息的结构,这个结构如下:

struct mymesg{   long mtype;char mtext[512];}

该结构必须包含一个长整型成员变量,用来标志这个消息的类型。第二个成员就用来指定存放我们消息。

nbytes: 消息长度(不包括长整型成员变量的长度)。

flag:一般指定为IPC_NOWAIT,表示非阻塞状态。

该函数成功执行时返回0,否则返回-1。

(3)从消息队列中获取消息

     ssize_t msgrcv(int msqid  ,  void *ptr  , size_t  nbytes , long  type , int flag);

该函数的参数更多,不过大部分与msgget函数的参数类似。

msqid :消息队里的ID。

prt:与msgget一样。

nbytes:获取消息的长度。

type: 获取消息的类型,上面我们说过prt指向的结构体,有一个参数是指定消息的类型,我们在获取消息时,就要指定这个类型。如果type为0,就获取队列中的第一个消息。如果它的值大于0,将获取指定类型的消息,如果小于0,就获取类型等于或者小于type的绝对值的第一个消息。

flag:一般指定为IPC_NOWAIT。

该函数执行成功后返回消息的数据部分的长度,以字节为单位,否则返回-1。

需要说明的是,从msqid代表的消息队列中读取一个type类型的消息,并把消息存储在msgbuf结构中,在成功地读取了一条消息以后,队列中的这条消息将被删除。

(4)控制消息队列

       int msgctl(int msgid , int command , struct msgid_ds *buf);

该函数用来控制消息队列,它与共享内存的shmctl函数类似,其参数意义为:

msgid: 为获取消息队列的标识符。

command:该参数说明对由msgid指定的队列要执行的命令:

   IPC_STAT:取此队列的msqid_ds结构,并将它存放在buf指向的结构中。

   IPC_SET:按由buf指向结构中的值,设置该队列的msqid_ds结构,不过该命令需要有足够的权限才能执行。

   IPC_RMID:删除消息队列。

buf:是指向msgid_ds结构的指针,我们知道,在创建一个消息队列的时候,内核为每一消息队列都会指定一个关联结构,该结构包含了该消息队列的相关信息,msgid_ds就是这样的一个结构。

该函数成功时返回0,否则返回-1.

说太多理论的东西可能不太好理解,下面我们就来写一个实例程序,利用消息队列方式实现两个不相关进程间的通信:

 发送进程程序:

#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <unistd.h>#include <string.h> #define MAX 256struct msgbuf    {       long int mtype;       char mtext[MAX];     };void main(){   int mspid;   key_t key;     int ret;   struct msgbuf mymsg;      //创建一个消息队列,首先获取键值   key = ftok("/home" , 1);   mspid = msgget(key ,IPC_CREAT|0666);   if(mspid==-1)          {               printf("creat the queuefailure\n");               return;               }       //向消息队列中填入数据,需要定义一个结构体   mymsg.mtype = 1;   strncpy(mymsg.mtext , "it is a memsg_queue test!" , 30);        ret = msgsnd(mspid , &mymsg , 256 ,IPC_NOWAIT);               if(ret == -1)           {               printf("send memsage failure\n");               return;             } }

接收进程程序:

#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <unistd.h>#include <string.h> struct msgbuf    {       long mtype;       char mtext[256];         };void main(){       int msqid;   key_t key;     int size;   struct msgbuf mymsg;      //获取一个消息队列,首先获取键值   key = ftok("/home" , 1);   msqid = msgget(key ,IPC_CREAT|0666);   if(msqid==-1)          {               printf("creat the queuefailure\n");               return;               }                       //读取一个消息队列中的内容   msgrcv(msqid , &mymsg ,sizeof(mymsg.mtext),1 , IPC_NOWAIT);   printf("the msg is : %s\n",mymsg.mtext);       //删除消息队列   if( msgctl(msqid , IPC_RMID , 0) == -1)           {               printf("delete the queuefailure\n");               return;                }  }

        发送进程程序创建一个消息队列,并向其中写入“it is a memsg_queue test!“这条消息语句,接收进程就获取这个消息队列,然后取出其中的消息,并打印出来,程序中关键的地方都有解释,需要注意的就是消息队列结构体的长整型,发送进程和接收进程此值一定要对应,否则读不出要的消息。打开linux命令行,在命令行中编译运行这两个程序,先运行发送进程,然后运行接收进程,可以发现我们的接收进程正确的获取了我们消息队列中的消息。有个细节大家注意没,我们运行发送进程后,在运行接收进程可以接收到消息,然后再运行我们的接收进程却收不到消息,这是为什么?我们前面在学习共享内存的时候,写入进程写入数据后,我们读取进程可以多次读取到数据,可是在消息队列中却只能读一次,原因是前面我们提到了在成功地读取了消息队列中的一条消息以后,队列中的这条消息将被删除。因此要想多次读取同样的消息,就得让发送进程多次发送。

以上便是linux进程通信之消息队列的简单介绍,希望得到指正。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 dnf88级没任务了怎么办 0号柴油冻住了怎么办 不小心喝了生水怎么办 不小心吃了蟑螂怎么办 以租代购还不起怎么办 孩子被教官打了怎么办 三岁宝宝叛逆期怎么办 三岁宝宝很叛逆怎么办 孩子不听话怎么办有什么方法呢 打了三岁的宝宝怎么办 2岁半宝宝不听话怎么办 心里素质不好容易紧张怎么办 孩子二年级成绩差怎么办 遇到素质低的人怎么办 孩子上课注意力不集中怎么办 素质报告册丢了怎么办 潞城镇剩下5个村怎么办 高三复读生学籍怎么办 被检精子总数少怎么办 前向运动精子17%怎么办 精子形态正常率1怎么办 精子形态正常率2怎么办 精子头部畸形率高怎么办 椎底动脉供血不足怎么办 颈椎动脉供血不足怎么办 颈椎病引起头晕脑供血不足怎么办 淘宝店被释放了怎么办 被枣蝎子蛰了怎么办 六角螺丝拧花了怎么办 苹果螺丝滑丝了怎么办 六角螺帽拧花了怎么办 六角螺母拧花了怎么办 内六角螺丝滑丝怎么办 十字螺丝拧花了怎么办 梅花螺丝滑丝了怎么办 螺丝孔道滑丝了,怎么办 锅把铆钉松啦怎么办 膨胀螺丝孔大了怎么办 戒指不圆了怎么办妙招 眼镜框的腿断了怎么办 弹簧腿眼镜坏了怎么办