前言
上回书说到,共享内存的一些知识,我们再来看一个新东西:消息队列,其实它用起来和共享内存有点像,甚至调用的函数都差不多,参数啥的都能对应上。
其实,共享内存、消息队列、信号量这三个通信方式的IPC通信里的“御三家”,至于管道和信号为啥不算,俺也不知道。
什么是消息队列
消息队列本质上是一个链表,很像之前管道里讲的:管道的本质是队列,就很奇怪,说是消息队列,本质却不是一个队列,而是叫作链式队列,和之前的管道队列是有区别的!
那有了管道还需要这个消息队列干嘛呢,当然是因为消息队列更强大嘛。
如下图所示:为消息队列在内存中分布的示意图
我们可以看到:这是一个链表的形式,一个结点指向下一个结点,直到最后一个。我们仔细看看每个结点里都有什么:第一个是指针,链表必须要有的东西,略过。第二个叫type
,这个type有值为100,为200……什么意思,100是一个代号,表明该结点存放数据的“种类”,type
不同的结点是不能看作相同类型的数据的,即使他们都是整型且数据一模一样。有了这个type,我们就可以迅速查到所有类型为100的结点,其他类型的结点不受影响。
往下看:length
表明当前节点数据段的长度,data
当然就是结点里存放的数据啦。
创建一个消息队列
创建消息队列的函数原型:
int msgget(key_t key, int msgflg);
是不是和共享内存的
int shmget(key_t key, size_t size, int shmflg);
很像?
其实他们的参数含义也是一样的:
key:可以设key值为IPC_PRIVATE
,无亲缘关系进程间通信我们使用函数key_t ftok(const char *pathname, int proj_id);
获取一个唯一的key值
msgflg:指明共享内存的权限,就像open函数中的mode参数一样,key值对应得共享内存不存在时需要使用IPC_CREAT
作与操作。
消息队列不需要像共享内存那样需要将内存连接到进程地址空间才能使用,所以方便不少。
删除消息队列函数原型:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msqid:是msgget()函数返回的消息队列标识符。
cmd:是要采取的操作,它可以取下面的三个值 :
IPC_STAT
IPC_SET
IPC_RMID:删除消息队列
buf:是一个结构指针,删除消息队列时设为NULL。
写入和读取函数:
int