Linux系统编程---进程间通信-消息队列

消息队列

消息队列也是一种进程间通信方式,它提供了两个不相关进程间传递数据的方式。消息队列实际上是操作系统在内核为我们创建的一个链式队列,通过这个队列的标识符key,多个进程可以通过向队列中添加节点或获取节点来进行数据传输。这个队列中的节点有一个消息类型来标识不同进程所发送或接受的数据类型。消息队列的生命周期随内核。

内核为每个IPC对象维护了一个数据结构
在这里插入图片描述
在这里插入图片描述

消息队列结构:
在这里插入图片描述
在这里插入图片描述

消息队列有关操作函数

//头文件
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/ipc.h>
 
key_t ftok(const char *pathname, int proj_id); //获取key值
int msgget(key_t key, int msgflg);//创建消息队列,成功时,返回值为唯一一个消息队列标识符
int msgrcv(int msqid, void *msg_ptr, size_t msg_sz, long int msgtype, int msgflg);//发送消息
int msgsnd(int msqid, const void *msg_ptr, size_t msg_sz, int msgflg);//接收消息
int msgctl(int msqid, int cmd, struct msqid_ds *buf);//消息队列控制函数

第一步,消息队列涉及三个东西,分别是键(key)值,消息队列标识符,和消息类型。key值是存在于IPC对应的结构体中,消息队列操作的第一步,就是获取一个key值,也就相当于创建了一个IPC对象,这个key值就对应了这个IPC对象,我们可以通过上面的ftok函数来获取一个key值;

第二步,就是调用msgget函数来创建一个消息队列,其是就相当于创建了一个msq-_id的结构体,然后将里面的对应的成员赋值,比如里面的msg_perm 就是IPC的一个对象,这个对象里面的key值就是我么刚才ftok获得的,完毕之后,该函数会返回一个消息队列标识符,来标识该消息队列,以后,各个进程之间相互通信就利用该标识符找到对应的消息队列。

第三步,当进程之间确定了该往那个消息队列中发送或接收数据后,还得知道它要接受或发送数据的类型,因为消息队列中的数据很多,它要获得自己想要的数据时,就必须知道要获取数据的类型,这个数据类型格式就是下面这样:

typedef struct msg_buf
{
	long mtype;		 // 消息类型
	char mtext[100]; // 消息正文
	//…… ……          // 消息的正文可以有多个成员
}MSG;

消息类型必须是长整型的,而且必须是结构体类型的第一个成员,类型下面是消息正文,正文可以有多个成员(正文成员可以是任意数据类型的)。

接下来我们介绍每个函数的用法。

ftok函数

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

key_t ftok(const char *pathname, int proj_id);

功能: 获取键(key)值。
参数:
pathname路径名
proj_id:项目ID,非0整数(低8为有效)
返回值:
成功:返回key值 失败:-1

msgget函数

//头文件
#include <sys/msg.h>

int msgget(key_t key, int msgflg);

功能: 创建一个新的或打开一个已经存在的消息队列。不同的进程调用此函数,只要用相同的 key 值就能得到同一个消息队列的标识符。

参数:

key: ftok() 返回的 key 值

msgflg: 标识函数的行为及消息队列的权限,由9个权限标志位构成,其用法和创建文件时使用的mode模式一样。有以下取值:

IPC_CREAT:创建消息队列。
IPC_EXCL: 检测消息队列是否存在。

返回值:
成功:消息队列描述符 失败:-1

msgsnd函数

//头文件
#include <sys/msg.h>

int msgsnd(  int msqid, const void *msgp, size_t msgsz, int msgflg);

功能: 把一条消息添加到消息队列中
参数:
msqid: 消息队列的标识符。

msgp: 是一个指针,指向待发送消息结构体的地址。

msgsz: 消息正文的字节数,是不包含消息类型的long长整型 。

msgflg:函数的控制属性,控制当前消息队列满或到达系统上限时将要发生的事情 。其取值如下:

0:调用阻塞直到条件满足为止。
IPC_NOWAIT: 表示队列满不等待,消息没有立即发送,返回EAGAIN错误。

返回值:
成功:0 失败:-1

msgrcv函数

//头文件
#include <sys/msg.h>

ssize_t msgrcv( int msqid, void *msgp,  size_t msgsz, long msgtyp, int msgflg );

功能: 是从一个消息队列接收消息
参数:
msqid:消息队列的标识符,代表要从哪个消息列中获取消息。

msgp: 是一个指针,指向待发送消息结构体的地址。

msgsz:消息正文的字节数,是不包含消息类型的long长整型 。

msgtyp:消息的类型。它可以实现接受优先级的简单形式,可以有以下几种类型:

msgtyp = 0:返回队列中的第一个消息。

msgtyp > 0:返回队列中第一条消息类型为 msgtyp 的消息(常用)。

msgtyp < 0:返回队列中消息类型值小于或等于 msgtyp 绝对值的消息,如果这种消息有若干个,则取类型值最小的消息。

需要注意:在获取某类型消息的时候,若队列中有多条此类型的消息,则获取最先添加的消息,即先进先出原则。

msgflg:函数的控制属性。其取值如下:

0:msgrcv() 调用阻塞直到接收消息成功为止。

MSG_NOERROR: 若返回的消息字节数比msgsz字节数多,则消息就会截短到 msgsz 字节,且不通知消息发送进程。

IPC_NOWAIT: 没有消息可读时,不等待直接返回ENOMSG错误。
msgtype>0 且msgflg = MSG_EXCEPT,接受类型不等于msgtype的第一条消息

返回值:

成功:返回实际放到接受缓冲区里面的字符个数。

失败:-1

msgctl函数

//头文件
#include <sys/msg.h>

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

功能: 消息队列的控制函数
参数:
msgid:由msgget函数返回的消息队列标识码
cmd:是将要采取的动作,取值如下:

IPC_RMID:删除由 msqid 指示的消息队列,将它从系统中删除并破坏相关数据结构。

IPC_STAT:将 msqid_ds 相关的数据结构中各个元素的当前值存入到由 buf 指向的结构中。相对于,把消息队列的属性备份到 buf 里。

IPC_SET:将 msqid 相关的数据结构中的元素设置为由 buf 指向的结构中的对应值。相当于,消息队列原来的属性值清空,再由 buf 来替换。

返回值:

成功:0
失败:-1

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值