System V 消息队列概念以及相关函数(msgget、msgsnd、msgrcv、msgctl)介绍
System V 消息队列
- 消息队列是半双工的通信方式
1.1 创建一个消息队列
消息队列的特点:消息只能一条的读取,不能多读取,也不能少读取,每条消息有一个类型,可以按照消息的类型读取
创建或者打开一条消息:
/************************* 函数功能:创建或者打开一条消息队列 返回值: If successful, the return value will be the message queue identifier (anonnegative integer), otherwise -1 with errno indicating the error. *************************/ #include <sys/types.h> #include <sys/ipc.h> include <sys/msg.h> int msgget(key_t key, int msgflg); /*参数 key:键值,用来生成标识符 msgflag:可以指定IPC_CREATE, IPC_EXCL等标记用 | 符号连接起来 */
- 通过key值与指定的键值对应的队列匹配,如果匹配成功,返回既有队列的标识符,如果指定了IPC_CREATE, IPC_EXCL等标记,返回相关错误,如果没有匹配成功,但是指定了IPC_CREATE标记,创建一个新的消息队列对象
1.2 交换消息
消息的常规形式
struct mymsg {long mtype; /*Message type*/char mtext; /*Message body*/ } /*这个结构可以由程序员自己决定,只是一般情况下的消息结构体是这样*/
发送消息
/***************************** 函数功能:发送一条消息 返回值: On failure both functions return -1 with errno indicating the error,otherwise msgsnd() returns 0 and msgrcv() returns the number of bytesactually copied into the mtext array. *****************************/ #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); /*参数: msqid:消息队列的标识符 msgp:指向一个消息结构 msgsz:消息结构中消息本体的大小 msgflg:位掩码的组合IPC_NOWAIT:执行一个非阻塞的发送操作,通常消息队列满的时候,msgsnd调用会阻塞,如果设置了这个标记,不会阻塞,会直接返回一个EINTR错误,并且该系统调用被打断之后,不会自动重启,就算设置了SA_RESETART标记 */
接受消息
/***************************** 函数功能:接受一条消息 返回值: On failure both functions return -1 with errno indicating the error,otherwise msgsnd() returns 0 and msgrcv() returns the number of bytesactually copied into the mtext array. *****************************/ #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg); /*参数: msqid:消息队列的标识符 msgp:指向一个存放消息结构的缓冲区 msgsz:指定了msgp指向的mtext字段(消息本体)最大能够容纳的大小,如果队列中消息大小超过这个字段,就不会从队列中读取消息,而是返回E2BIG错误 msgtyp:消息的读取并非是先进先出,而是按照msgtype的类型进行选择性的读取 1:msgtyp==0:删除队列中第一条消息,并且返回给调用进程 2:msgtyp>0:将队列中第一个mtype等于msgtyp的消息删除并将其返回给调用进程,其它不相等不管,让它还是存在于队列中 3:msgtyp<0:将等待队列中mtype值最小并且其值小于或者等于msgtyp的绝对值的第一条消息会被删除返回给调用进程 msgflg: IPC_NOWAIT:执行一个非阻塞操作,没有匹配的消息类型,返回ENOMSG错误 MSG_EXCEPT:当msgtyp>0时候,将队列中mtype不等于msgtyp的消息强制删除并且返回给调用者,这个标记linux特有的,需要定义_GNU_SOURCE之后才可以,等于msgtyp的消息忽略,让其存在于队列中 MSG_NOERROR:如果消息中mtext字段大于msgsz,会截断mtext字段的数据大小为msgsz返回给调用者,截断剩余的数据会丢失,没有这个标志的话是不会发生截断的,而是直接报错 */
1.3 消息队列控制操作
函数功能:在标识符msqid的消息队列上执行控制操作
返回值:Return 0 On success,or -1 on error
函数原型:
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数:
- msqid:消息队列的标识符
- cmd:在消息队列上操作的相关命令
- IPC_RMID:立即删除消息队列对象及其关联的msqid_ds数据结构,队列中所有消息会丢失,所有被阻塞的读者和写者进程立即醒来,msgsnd和msgrcv会失败返回EIDRM,这个操作会忽略第三个参数
- IPC_STAT:将这个消息队列关联的msgid_ds数据结构的副本保存在buf指向的缓冲区
- IPC_SET:将buf指向的缓冲区提供的值更新这个消息队列关联的msqid_ds数据结构中的被选中的字段
1.4 消息队列关联数据结构
每个icp对象的关联数据结构中共有的一部分:
- 该部分的讲解在第45章中已经完成,这里主要对消息队列关联数据结构独有的字段进行分析
消息队列的关联数据结构
- msgqnum、msglen_t属于无符号整型
- msg_stime:队列创建之后,初始化为0,每次msgsnd调用会将这个字段设置为当前时间,新纪元到现在的秒数
- msg_stime:队列创建之后,初始化为0,每次msgsrcv调用会将这个字段设置为当前时间,新纪元到现在的秒数
- msg_ctime:队列创建之后,初始化为当前时间,每次IPC_SET操作会将这个字段设置为当前时间,新纪元到现在的秒数
- __msg_cbytes:队列创建之后,初始化为0,后续每个msgsnd或者msgsrcv调用都会把字段更新为队列中所有mtext字段包含的字节的总和
- msg_qnum:队列创建之后,初始化为0,后续每个msgsnd调用递增这个字段,后续每个msgrcv调用递减这个字段,以反映出队列中消息的总数
- msg_qbytes:这个字段为队列中所有消息的mtext字段包含的字节的总和设置了一个上限,队列创建之后,初始化为MSGMNB,特权进程可以使用IPC_SET操作更改该字段的值在0到INT_MAX之间,也可以在/proc/sys/kernel/msgmnb文件中做修改,以保证后续队列创建初始值以及非特权进程所能进行的修改
- msg_lspid:队列创建之后,初始化为0,后续每个msgsnd调用,会把该字段的值设置为调用进程的pid
- msg_lrpid:队列创建之后,初始化为0,后续每个msgrcv调用,会把该字段的值设置为调用进程的pid
1.5 消息队列的限制
- 大多数UNIX实现会对System V消息队列操作施加各种各样的限制,比如系统级创建消息队列的数量、单条消息可以写入的字节数、一个消息队列一次最多可以保存的字节数、系统中消息队列能存放的消息总数,linux下可以在/proc/sys/kernel里面查看并且修改这些限制 ,具体可以查阅书籍本章节
1.6 使用消息队列实现客户端-服务器应用程序
- 服务器和客户端之间可以采用一个消息队列,但是这里会存在一些问题:
- 注意区分消息类型,这里一般用进程ID作为消息类型
- 多个并行的写入可能会造成死锁等问题
- 所以我们这里最好采用多个消息队列,每一个客户端一个,每一个服务器一个,但死锁的问题还是需要自己解决
1.7 使用System V 消息队列的缺点:
- 优点:可以根据消息类型选择性的读取队列中的消息
- 缺点:
- 消息队列的引用采用标识符,而不是文件描述符
- 使用键而不是文件名来标识消息队列会增加额外的程序设计复杂性
- 内核不会对使用消息队列的进程引用计数
- 消息队列有很多种限制
- 总体上来讲最好避免使用System V 消息队列,应该尽量考虑其它方案,比如POSIX 消息队列,更加有难度的是基于多文件描述符的通信信道
System V 消息队列概念以及相关函数(msgget、msgsnd、msgrcv、msgctl)介绍相关推荐
- msgget();msgsnd();msgrcv();msgctl(); 消息队列 Linux进程间的通信方式之消息队列
Linux进程间的通信方式 ----消息队列. 消息队列和共享内存类似 消息队列它允许一个或多个进程向它写消息,一个或多个进程向它写读消息. 消息队列存在于系统内核中,消息的数量受系统限制. 我们来看 ...
- 细说linux IPC(十):system V 消息队列
[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] system V消息队列和posix消息队列类 ...
- 【Linux】system V 消息队列 | system V 信号量(简单赘述)
文章目录 1 . system V 消息队列(了解) 接口 查看消息队列 2.system V 信号量 (了解) 1.进程互斥等概念的理解 2.认识信号量 3. 接口 这两部分主要是了解即可,为后面学 ...
- linux进程间通信:system V消息队列
文章目录 基本介绍 编程接口 代码实例 消息队列的发送和接收 消息队列中的消息对象的属性控制 基本介绍 支持不同进程之间以消息(messages)的形式进行数据交换,消息能够拥有自己的标识,且内核使用 ...
- System V 消息队列
一.System V 消息队列 有一个队列,队列存放各种消息.每个进程可以把数据封存在消息中,再放入队列.每个进程都可以拿到消息队列,再从中取出/放入消息. 消息队列也有管道一样的不足,就是每个消息的 ...
- System V消息队列
简介 这篇笔记中介绍了消息队列的基本知识和Posix消息队列.这篇笔记主要学习记录System V消息队列,并对比两个消息队列. System V消息队列是更早的一个消息队列的实现.Posix消息队列 ...
- Linux网络编程之System V消息队列
System V消息队列函数: #include<sys/types.h> #include<sys/ipc.h> #include<sys/msg.h> int ...
- (P26)system v消息队列:msgsnd函数 ,msgrcv函数
文章目录 1.msgsnd函数 2.msgrcv函数 1.msgsnd函数 功能:把一条消息添加到消息队列中原型:int msgsnd(int msqid, const void *msgp, siz ...
- 06.System V 消息队列
1.概述 System V消息队列使用消息队列标识符(message queue identifier)标识.具有足够特权的任何进程都可以往一个给定队列放置一个消息,具有足够特权的任何进程都可以从一个 ...
最新文章
- Android--添加子视图(addView和setView)
- rhel配置磁盘分区_rhel配置磁盘分区_centos系统三套硬盘分区方案[图文设置版]
- [原]零基础学习在Android进行SDL开发系列文章
- 前端面试题 微信小程序
- ubuntu14.04修改limits.conf后链接限制仍然不生效
- Security+ 学习笔记17 公钥基础设施
- USB速度异常的问题
- Protel99se基本教程 Protel 99SE从零开始学习教程视频教程
- 四、OSPF配置实验
- 学大伟业:如何利用课余时间学习物理竞赛,搞定自主招生?
- 用spark实现单词统计
- 武汉安全员ABC证报名条件有什么要求?甘建二
- 经历--比赛绿盟_安全研究员
- NYIST_ACM Ranking List FAQ
- H5+JavaScript 剪刀石头布小游戏完整代码
- Linux的网络测试命令(转载)
- 西门子消防主机FC18配套CAN光端机进行光纤冗余环网组网测试
- msr颜色复原matlab程序,Retinex 图像去模糊(含MATLAB代码)
- 浪潮服务器改uefi引导,关于windows系统的uefi启动方式,两种修复引导的方法
- bilibili如何空降