进程间通讯(三)消息队列

一、消息队列

1、定义:

消息:是一种数据(不仅仅是数据消息,它包括数据和类型);队列:它的数据结构是“先进先出”。

消息队列:是一种临时存储消息的队列,完成进程之间的数据传递。它的特点是:不是完全的先进先出,相当于是有优先级的队列。

2、特点:

与管道相比:它也提供了一种在两个不相关的进程之间传递数据的方法,但消息队列的优点在于它独立于发送和进程而存在。不同的是管道发送的数据没有类型,读取数据端无差别从管道中按照数据的前后顺序依次读取数据;而消息队列数据有类型,读取端根据类型读取特定的数据。

比如有A、B、C三个进程,A进程负责写,B、C负责读,如果是管道文件,无法控制B、C两个进程的先后顺序;但如果是消息队列,A发送a、b类型的数据,则读的时候就可以B读取a类型的数据,C读取b类型的数据,这样与先后顺序就没有关系,只与数据类型有关。就哪怕有几百个数据,但你要的类型只有一个那也只读一个。所以说在多进程之间传递数据,并且数据有指定方的时候用消息队列。

和管道相同的一个不好的地方是它们都有长度限制,消息队列的每个数据块都有一个最大长度的限制,系统中所有队列所包含的全部数据块的总长度也有一个上限。

与信号量相比:都以内核对象来确保多进程访问同一个消息队列(和管道文件一样,管道文件在磁盘的目录树中存在)信号量进行进程同步控制,不发送数据;消息队列发送实际数据。

内核创建一个内核对象,数据缓存在内核上。

3、操作:

(1)创建或获取:因为有内核对象,所以先得把内核对象创建出来,让另一端直接获取。在这和信号量相比呢,消息队列只负责创建,不需要初始化,所有创建和获取依次完成;

int  msgget ( ( key_t ) key,  int  flag );

key:提供键值来命名某个特定的消息队列;           flag:权限 IPC_CREAT:如果存在,直接获取;如果不存在,则创建;        信号量的话是先获取,获取失败再创建。

(2)发送消息:

int  msgsnd (int  msgid ,void * ptr ,size_t size ,int  flag);

msgid:要被写入的消息的消息队列;           

ptr:写的消息队列的内容,(ptr指向一个结构体,因为消息包括数据和类型)         

size:写的数据的长度;(实际发送数据的大小)         

flag:控制(因为消息队列有大小,所以如果发送的时候还有空间,继续进行;如果没有空间了,就根据这个参数知道接下来干什么) 

管道文件是如果读的时候没有数据则阻塞,写的时候,如果已经写满了,则堵塞;

消息队列是如果读的时候有空间则读,没空间就要根据第4个参数flag去指定函数接下来进行的行为。消息队列的大小不是队列能放多少个消息,而是能放多长的数据。

(3)获取消息:

int  msgrcv(int  msgid ,void   * ptr ,size_t size ,long  type ,int  flag);

*prt:相当于buff,消息获取后得缓存下来,ptr指向存它的地方;

size:buff的大小,能读多少都多少,后面的都截取掉;

type:获取消息的类型;

(4)删除消息:

int  msgctl (int  msgid ,int  cmd,struct msgid_ds  *buff);

cmd:IPC_STAT:获取属性(结构体);           IPC_SET:设置属性;          IPC_RMID:删除(不需要后面参数 )




由两次结果可以看出,数据类型不同,打印的结果不同,说明消息队列不像管道文件一样在大小范围之内都读取。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值