进程通讯(四)--消息队列

18 篇文章 0 订阅
17 篇文章 0 订阅
消息队列和管道很像。但它比起管道不需要固定进程的只读和只写,通讯间的进程都可以读写,并且支持多个进程。
  而消息队列发送的消息 实际是一个消息类型和实际的消息。消息类型是什么?它其实是一个长整型数字,具体多少完全由用户来定义,为的是读消息时可以根据这个类型来调整读取的优先级顺序。
  所以说消息队列发送的是数据块,一般发送的消息就定义为以下的结构体。
 struct msg
{
 long type;//自定义的消息类型
    char buff[N] ;   //实际的数据比如字符数组形势的

}

到时候读取消息的时候,不必像管道一样必须读第一个,假如有加急消息的话,读取函数中可以取加急消息的类型,这样的话就会优先读取相同类型的第一个消息,比如56类型的。

   消息队列的具体使用
  这里要四个函数
  1.int msgget(key_t key,int msgflg);
   和信号量差不多的获取函数,不过比起信号量获取后还要semctl初始值来说,第一次获取消息队列在此函数第二个参数加|IPC_CREAT 就直接创建新的队列,不用进行初始化。key值仍为用户随意定义的值,第二个就是权限 加  IPC_CREAT等宏(可选),返回值-1表示失败,成功返回标识符msgid。

2.int msgsnd(int msgid,const void *msg_ptr,size_t msg_sz,int msgflag)
  第一个参数为msgget函数标返回的识符,无需多说。
  第二个就是我们要发送的消息的指针,就是上面定义的那个  消息类型+实际消息 的结构体指针。
  第三个参数就是发送的实际消息的长度,即从第二个参数指针后跳过一个long类型长度开始取内容。
  第四个参数是一些宏,控制消息队列满了或者超过系统范围的一些情况,目前我们基础的都写0就好。

3.int msgrcv(int msgid,void *msg_ptr,size_t msg_sz,long int type,int msgflg);
前三个参数和msgsnd的前三个差不多,不过值得注意的是这里的第二个参数是要接收消息的指针,即自己定义的接受消息缓冲区结构体的指针。
第四个参数就比较有意思了,也算是消息队列的核心用法吧,这里接收的消息就会按第四个参数里long型type值去接受,即假如消息队列里有一个1234类型的消息在中间,我要是第四个参数就写1234,那么就会优先接收到那个1234类型的消息,不像管道一样,必须先接收队头的消息。还有几个用法就是,如果写成0,那么就会·按着消息队列的顺序读消息。如果写成-n,那么只会读类型小于等于n的消息
第五个参数也是一些宏,处理消息队列中没有第四个参数的值的类型的情况。一般我们也取0吧。
最后返回值-1表示失败,成功返回第二个参数接受到的字节数。

4.int msgctl(int msgid ,int command,struct msgid_ds buf);
和其他方式IPC的控制函数一样,第二个参数三个值
IPC_STAT, IPC_SET, IPC_RMID
当第二个参数为IPC_RMID,表示要删除消息队列,可以无视第三个参数,设为0就好。
至于IPC_STAT, IPC_SET
前者是第三个参数的结构体设为当前的消息队列关联值。
后者是把消息队列的关联值设为第三个参数结构体里的值。
第三个参数的结构体就是一些用户 组 ,访问权限之类的东西。

最后还是用一道题来示范下用法吧。
题目如下,A进程负责输入类型和数据,BC进程分别负责读取类型为1000和2000的数据。
其实BC可以写成一份代码,在main函数传参分情况讨论就好
A进程代码:





BC进程代码:





结果如下:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值