ipc之消息队列
消息队列以链表的方式将消息存储于内核中,调用msgsnd,msgrcv函数往消息队列里面投送,取出指定的消息。
- 创建一个消息队列
生成一个消息队列或者获取已有消息队列id
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> int msgget(key_t key, int msgflg);
msgget函数返回key值对应的消息队列id。
1. key是一个用来与一个ipc对象进行对应的东西,起到在内核中标识的作用。
2.返回的id起到的是外部也就是我们应用层的标识作用,例如所有操作消息队列的函数,都是用msgid来唯一确定一个消息队列。
3.msgflg用来指定消息队列的权限,操作属性,高位为操作属性,地位为操作权限,比如msgflg通常使用的高位值:
IPC_CREAT:用来创建一个消息队列
IPC_EXCL:查询由key指定的消息队列释放存在
IPC_NOWAIT:之后的消息队列操作都为非阻塞
一个例子 msgget(key, IPC_CREAT|); 创建由key指定的消息队列,操作权限为0666。
id = msgget(key, ) 得到key值对应的消息队列的id。
当key值为 IPC_PRIVATE 时,或者key值不为它但是msgflg指定了 IPC_CREAT ,则创建一个新的消息队列,如果这个消息队列不存在时。指定 IPC_PRIVATE 为key值时,总是创建一个新的消息队列,生成的消息队列key值为0。
由此可见获得消息队列操作 ID是很关键的,一般有3种方法获得id:
1.指定key值为 IPC_PRIVATE ,创建一个新的消息队列,让后将id值写入一个文件,另一个进程读取该文件,获得id值,这样2个进程就可以通过这个消息队列通信了。
2.手动指定key值为某个值,多个进程都看看得到这个key,这样做的问题就是可能有一个key值和指定key值一样的消息队列存在了,需要处理这样的错误,换一个key值。
3.使用ftok函数生成一个key,同一个key调用msgget得到的id肯定是相同的。
#include <sys/types.h>
#include <sys/ipc.h> key_t ftok(const char *pathname, int proj_id); (proj_id is 1-255)
ftok函数的实现是通过stat函数获取pathname的st_dev,st_ino成员(部分位)和proj_id(只用低8位)进行组合生成一个key值,这样做的话,只要pathname和proj_id确定,那么key值基本就确定。
1.但是这个函数依然存在一种可能就是pathname不一样,proj_id一样,仍然得到一个一样的key,这是因为st_dev,st_ino成员数据被截断了,可能刚好保留的数据是相同的。
2.还有一点就是必须确保pathname这个文件全程都不会被改动,否则A进程获得key之后,在B进程获取key之前,修改pathname这个文件,从而影响st_dev,st_ino,导致B得到的key和A不一样,虽然pathname,proj_id并没有变。
- 消息队列属性描述
通过 msgctl可以获得,设置,删除消息队列
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> int msgctl(int msqid, int cmd, struct msqid_ds *buf);
它的使用类似io操作中的ioctl。cmd有如下值:
IPC_STAT:获取由msgid指定的消息队列的描述结构体,存放于buf中。
IPC_SET:设置消息队列的描述结构体
IPC_RMID:立刻删除指定key值的消息队列,key值存放于buf结构体中。如果删除后仍有进程读写这个消息队列,则返回EIDRM错误。
一般,如果消息队列出错了,使用IPC_RMID删除消息队列,释放它在内核中占有的资源。
- 消息的发送和接收
消息队列是在一定的空间内建立一个链表,每次都将最近一个发送的消息放在队列链表的末尾,当取走一个消息时,它占据的相应空间就释放出来用以给后面要加入的消息使用。
通过函数msgsnd,msgrcv可以实现对指定消息队列进行消息发送和接收。
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
msgsnd:向msgid指定的消息队列末尾追加一个由msgp指向的消息,消息内容大小为msgsz。通常消息通过一个结构体进行描述,一般形式如下:
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[]; /* message data */
};
这个结构体可分为2个部分,mtype用以标识消息类型,mtext这个部分就是消息的内容,可以是你想要的描述消息内容的任何形式如数组,结构体等等。msgsnd,msgrcv里面所指定的消息大小msgsz指的是消息结构体内容mtext部分的长度,不包括mtype!消息类型必须大于0,至于为什么,看到msgrcv函数时就可以知道。
msgflg:通常有2种取值:
0:默认值,忽略标识位。消息发送时,当消息队列里面的空间超过限制值时,msgsnd将发生阻塞,直到空间腾出来可以满足需求(就是有人读走消息),或者msgid指定的消息队列已被删除,或者捕获一个信号,否则立马返回。
IPC_NOWAIT:非阻塞,空间不足时不阻塞,而是返回一个错误值EAGAIN。
一个阻塞的msgsnd是可以被信号中断的。中断后返回错误,错误值EINTR。msgsnd函数一旦被信号中断,永远都不会重启调用,即便安装信号处理函数时指定了重启标识SA_RESTART。因此对于一个阻塞的消息队列,要注意对其错误的处理。
msgrcv:从msgid指定的消息队列里面取出由msgtyp指定类型的消息存放于msgp指向的空间。取出的消息数据大小由msgsz指定。成功时,返回拷贝到mtext中实际的字节数。
msgtyp有3种情况,用以控制取出消息的方式:
等于0:取出队列中的第一个消息,这样可以以先进先出的方式取消息(因为msgsnd都是把消息添加到消息队列的最后面)。
大于0:取出mtype于msgtyp相同的消息。
小于0:取出消息队列中mtype值小于等于msgtyp绝对值的所有消息中mtype值最小的那个消息。(假设mtype设定为消息的优先级,这种方式可以用于控制消息队列取消息的优先级)
从上面的描述可以看出这就是为什么消息结构体中mtype值为什么一定要大于0的原因。
msgflg有多种组合方式:
0:忽略标识位,当消息队列中无指定消息时阻塞,直到有指定类型消息,或者消息队列被删除,或者被信号中断。后面2种都会返回错误。
IPC_NOWAIT:非阻塞方式读取消息。无消息时返回ENOMSG
MSG_NOERROR:如果消息类型匹配上了,但是消息数据大小大于msgrcv指定的msgsz,则返回错误E2BIG。但是如果指定了MSG_NOERROR标识,则过大的消息数据按照msgsz指定的大小截断。
MSG_EXCEPT:如果msgtyp大于0,指定此标识表示按照先进先出的方式取出第一个非msgtyp的消息。
一个消息队列中的消息大小是可以不一样的,即便是同一类型的消息,这样当消息数据是变长时,避免出现空间的浪费。配合不使用MSG_NOERROR和对错误的判断可以提取出同一类型消息中指定长度的消息。
ipc之消息队列的更多相关文章
- System V IPC(1)-消息队列
一.概述 System V三种IPC:消息队列,信号量,共享内存.这三种IPC最先出现在AT&am ...
- Linux 进程间通信(一)(经典IPC:消息队列、信号量、共享存储)
有3种称作XSI IPC的IPC:消息队列.信号量.共享存储.这种类型的IPC有如下共同的特性. 每个内核中的IPC都用一个非负整数标志.标识符是IPC对象的内部名称,为了使多个合作进程能够在同一IP ...
- 进程间通信IPC:消息队列,信号量,共享内存
2015.3.4星期三 阴天 进程间通信:IPC 文件对象:记录文件描述符,文件开关等 IPC标示符:系统全局的流水号两个进程要通信,打开的是唯一的对象进行通讯,通过key操作 XSI IPC:消息队 ...
- IPC之消息队列详解与使用
一. 概念 消息队列就是一个消息的链表.对消息队列有写权限的进程可以向其中按照一定的规则添加新消息:对消息队列有读权限的进程可以从消息队列中读出消息.消息队列是随内核持续的.下面介绍三个概念: ...
- System V IPC 之消息队列
消息队列和共享内存.信号量一样,同属 System V IPC 通信机制.消息队列是一系列连续排列的消息,保存在内核中,通过消息队列的引用标识符来访问.使用消息队列的好处是对每个消息指定了特定消息类型 ...
- 进程间通信——XSI IPC之消息队列
进程间通信XSI IPC有3种:消息队列.共享内存.信号量.它们之间有很多相似之处,但也有各自的特殊的地方.消息队列作为其中比较简单的一种,它会有些什么东西呢,来一起探讨探讨.. 消息队列结构 消息队 ...
- 四十九、进程间通信——System V IPC 之消息队列
49.1 System V IPC 介绍 49.1.1 System V IPC 概述 UNIX 系统存在信号.管道和命名管道等基本进程间通讯机制 System V 引入了三种高级进程间通信机制 消息 ...
- UNIX IPC: POSIX 消息队列 与 信号
POSIX消息队列可以注册空队列有消息到达时所触发的信号,而信号触发对应的信号处理函数. 下面是一份基本的消息队列和信号处理结合的代码(修改自UNIX网络编程:进程间通信) #include < ...
- UNIX IPC: POSIX 消息队列
首先在我的MAC OSX上试了一下虽然有_POSIX_MESSAGE_PASSING的宏定义,但是用gcc编译会提示没有mqueue.h头文件,先放一边.在Ubuntu上使用正常,不过POSIX消息队 ...
随机推荐
- Web前端测试题
JS题目: 在JavaScript中( )方法可以对数组元素进行排序. A. add()B. join()C. sort()D. length() 答案:http://hovertree.com/ti ...
- 关于c++数的进制的经验
默认状态下,数据按十进制输入输出.如果要求按八进制或十六进制输入输出,在cin或cout中必须指明相应的数据形式,oct为八进制,hex为十六进制,dec为十进制. 注意: 1.使用不带.h的头文件& ...
- 重新想象 Windows 8 Store Apps (59) - 锁屏
[源码下载] 重新想象 Windows 8 Store Apps (59) - 锁屏 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 锁屏 登录锁屏,获取当前程序的锁 ...
- 译 PrestaShop开发者指南 第四篇 深入PrestaShop核心开发
## 访问数据库 ### 数据库结构 PrestaShop的数据库表默认带有ps_的前缀,前缀在安装时可以自定义. 所有表名都是小写,以下划线分割.当一个表表示要在两个实体间建立连接时,表名中两个实体 ...
- STL---Codeforces675D Tree Construction(二叉树节点的父亲节点)
Description During the programming classes Vasya was assigned a difficult problem. However, he doesn ...
- linux怎么模糊查找一个文件
linux如何模糊查找一个文件 在当前目录下搜索指定文件: find . -name test.txt 在当前目录下模糊搜索文件: find . -name '*.txt' 在当前目录下搜索特定属性的 ...
- SQL SERVER获取数据库文件信息
MS SQL SERVER 获取当前数据库文件等信息,适用于多个版本: SELECT dbf.file_id AS FileID , dbf.name AS [FileName] , s.fi ...
- BaseServlet
1. 目的: 将提升Servlet的处理请求的能力,而不只限于doGet()/doPost()等请求. 让其Servlet能够自己根据请求,从而触发相应的方法进行处理. 2. 具体代码实现: impo ...
- Win10 FaceAPI小demo开发问题汇总
Win10 FaceAPI小demo开发问题汇总 最近使用微软牛津计划做一个小demo,使用FaceAPI做一个小应用,实现刷脸的功能.开发的过程中用到几个问题,具体如下: Stream 与IRand ...
- andriod 读取网络图片
来自:http://blog.csdn.net/jianghuiquan/article/details/8641283 Android手机上,我们常用ImageView显示图片,我们本章获取网络图片 ...