一、    概念

消息队列就是一个消息的链表。对消息队列有写权限的进程可以向其中按照一定的规则添加新消息;对消息队列有读权限的进程可以从消息队列中读出消息。消息队列是随内核持续的。下面介绍三个概念:

1;随进程持续:IPC一直存在,直至打开IPC对象的最后一个进程关闭该对象为止,如管道和有名管道

2;随内核持续:IPC一直持续到内核重新自举或者显示删除对象为止。如:消息队列,信号量,共享内存

3;随文件系统持续:IPC一直持续的显示删除该对象为止

System V消息队列目前被大量使用。

二、    消息队列的信息

结构msqid_ds用来设置或返回消息队列的信息,存在于用户空间;

struct msqid_ds
{
  struct ipc_perm msg_perm; /* structure describing operation permission */
  __time_t msg_stime; /* time of last msgsnd command */
  __time_t msg_rtime; /* time of last msgrcv command */
  __time_t msg_ctime; /* time of last change */
  unsigned long int __msg_cbytes; /* current number of bytes on queue */
  msgqnum_t msg_qnum; /* number of messages currently on queue */
  msglen_t msg_qbytes; /* max number of bytes allowed on queue */
  __pid_t msg_lspid; /* pid of last msgsnd() */
  __pid_t msg_lrpid; /* pid of last msgrcv() */
  unsigned long int __unused4;
  unsigned long int __unused5;
};

三、    打开创建消息队列

  消息队列的内核持续性要求每个消息队列都在系统范围内对应唯一的键值,所以,要获得一个消息队列的描述字,只需提供该消息队列的键值即可。msgget用于创建一个消息队列或打开一个现存的队列。

  int msgget(key_t key,int msgflag);

  创建一个新的消息队列或打开一个存在的消息队列。

  若成功则为消息队列描述字若出错则为-1。

  key: 是一个键值,由ftok获得,或直接给其常量也可;

  msgflg: 是一些标志位,数值有:IPC_CREAT(创建消息队列)、IPC_EXCL(  )、IPC_NOWAIT(  )或三者的或结果。

  比如说:msgflg =IPC_CREAT| IPC_EXCL|0666,意思是若不存在key值的队列则创建,否则如果存在则打开队列,0666意思与一般文件权限一样。3位八进制数代表本用户,同组用户,其它用户的读写执行权限。

在以下两种情况下,该调用将创建一个新的消息队列:

1.如果没有消息队列与健值key相对应,并且msgflg中包含了IPC_CREAT标志位;

2.key参数为IPC_PRIVATE;

还有注意的是:当创建一个新队列时,系统自动初始化struct msqid_ds结构的下列成员。

  ipc_perm结构按我们以前说的进行初始化。该结构中mode成员按flag中的相应权限位设置。

  msg_qnum,msg_lspid,msg_lrpid,msg_stime,msg_rtime都设置为0。

  msg_ctime设置为当前时间。msg_qbytes设置为系统限制值。

四、获得和修改消息队列属性,删除消息队列

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

  对消息队列进行多种操作

  若成功返回0,若出错返回-1  

  msqid: 消息队列ID,

  cmd:   要执行的操作,等同于信号量和共享存储的操作。

  buf:   此队列的struct msqid_ds结构,临时的 msqid_ds 结构体类型的变量。用于存储读取的消息队列属性或需要修改的消息队列属性

  该系统调用对由msqid标识的消息队列执行cmd操作,共有三种cmd操作:IPC_STAT(取得队列状态)、IPC_SET(设置队列属性)、IPC_RMID(删除消息队列)。

  IPC_STAT:该命令用来获取消息队列信息,返回的信息存贮在buf指向的msqid_da结构中;

  IPC_SET:该命令用来设置消息队列的属性,要设置的属性存储在buf指向的msqid_ds结构中;可设置属性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes,同时,也影响msg_ctime成员。

  IPC_RMID:删除msqid_ds标识的消息队列.

五、用消息队列发送和接收消息

  int msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg);

  从消息队列msqid中读取一个msgtyp类型的消息,并把消息存储在msgp指向的msgbuf结构体中。(在成功读取后,队列中的这条消息将被删除)

  成功返回0,失败返回-1.

  msqid: 消息队列ID

  msgp:接收存放的消息队列缓存结构,

  msgsz:消息数据长度

  msgtype:消息类型,=0读取队列中第一个数据

  msgflg:读取标志,

      IPC_NOWAIT(如果碰到没有满足条件的消息,立即返回,此时错误代码为ENOMSG),

      IPC_EXCEPT(与msgtype>0)配合使用,返回队列中第一个类型不为msgtype的消息,

      MSG_NOERROR:截断看超长数据。

  附:

  msgrcv()解除阻塞的条件三个条件:

  1.  消息队列中有了满足条件的消息(或使用了);

  2.  msqid代表的消息队列被删除;

  3.  调用msgrcv()的进程被信号中断;

  int msgsnd(int msqid, struct msgbuf *msgp, int msgsz, int msgflg);

  向消息队列发送一条消息。即将发送的消息存储在msgp指向的msgbuf结构中,消息的大小由msgze指定。

  成功返回0,否则返回-1。

  msqid:消息队列ID

  msgp:指向消息数据的指针

  msgsz:发送消息的大小

  msgflag:标志位

  附:msgp格式为:

  struct msgbuf{

long mtype; /*消息类型 must be > 0*/

char mtext[1]; /*消息数据 这是只是一个数组首地址,并非只有一个字符*/

};

我们可以把msgbuf结构看成是一个模版,程序员可以根据自己的需要来设计直接的消息结构。举例来说,如果某个应用需要交换由一个整数后跟一个8字节字符数组构成的消息,

那它可以如下定义自己的结构:

typedef struct my_msgbuf{

long mtypel

int    mshort;

char mchar[MY_DATA];

}Message;

对发送消息来说,有意义的msgflg标志为IPC_NOWAIT,指明在消息队列没有足够空间容纳要发送的消息时,msgsnd是否等待,0表示等待。

    造成msgsnd()等待的条件有两种:

1.当前消息的大小与当前消息队列中的字节数之和超过了消息队列的总容量;

2.当前消息队列的消息数(单位"个")不小于消息队列的总容量(单位"字节数"),此时,虽然消息队列中的消息数目很多,但基本上都只有一个字节。

msgsnd()解除阻塞的条件有三个:

1.不满足上述两个条件,即消息队列中有容纳该消息的空间;

2.msqid代表的消息队列被删除;

3.调用msgsnd()的进程被信号中断;

当msgsnd成功返回,与消息队列相关的msqid_ds结构得到更新,以标明发出该调用的进程ID(msg_lspid),进行该调用的时间(msg_stime),并指示队列中增加了一条消息。

六、消息队列的使用

【转】IPC-消息队列的更多相关文章

  1. IPC——消息队列

    Linux进程间通信——使用消息队列 下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信——使用命名管 ...

  2. linux IPC 消息队列(二)

    我在网上想找多进程之间的通信方式,发现有人写的消息队列很好,搬过来: common.h #ifndef __COMMON_H_ #define __COMMON_H_ #include <std ...

  3. linux IPC 消息队列

    消息队列函数原型 在建立IPC通讯时(如消息队列,共享内存)必须建立一个ID值.通常情况下,这个ID值由ftok函数得到 #inlcude <sys/types.h> #include & ...

  4. 进程间通信IPC:消息队列,信号量,共享内存

    2015.3.4星期三 阴天 进程间通信:IPC 文件对象:记录文件描述符,文件开关等 IPC标示符:系统全局的流水号两个进程要通信,打开的是唯一的对象进行通讯,通过key操作 XSI IPC:消息队 ...

  5. System V IPC 之消息队列

    消息队列和共享内存.信号量一样,同属 System V IPC 通信机制.消息队列是一系列连续排列的消息,保存在内核中,通过消息队列的引用标识符来访问.使用消息队列的好处是对每个消息指定了特定消息类型 ...

  6. 进程(守护进程--互斥锁--IPC机制--生产者模型--僵尸进程与孤儿进程--模拟抢票--消息队列)

    目录 一:进程理论知识 1.理论知识 二:什么是进程? 三:僵尸进程与孤儿进程 1.僵尸进程 四:守护进程 1.什么是守护进程? 2.主进程创建守护进程 3.守护进程 五:互斥锁(模拟多人抢票) 1. ...

  7. 【windows 操作系统】进程间通信(IPC)简述|无名管道和命名管道 消息队列、信号量、共享存储、Socket、Streams等

    一.进程间通信简述 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进 ...

  8. linux下的进程间通信之消息队列

    概念: 进程彼此之间可以通过IPC消息进行通信.进程产生的每条消息都被发送到一个IPC消息队列中,这条消息一直存放在队列中,直到另一个进程将其读走为止. 优点:可以通过发送消息来几乎完全避免命名管道的 ...

  9. Linux IPC System V 消息队列

    模型 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> ftok() //获取key ...

  10. System V IPC(1)-消息队列

    一.概述                                                    System V三种IPC:消息队列,信号量,共享内存.这三种IPC最先出现在AT&am ...

随机推荐

  1. Linux基础--用户和组管理

    1.账号管理相关文件 1)/etc/passwd    每一行都代表一个账号,有几行就代表有几个账号在你的系统中,不过需要特别留意的是,里头很多账号本来就是系统中必须要的,我们可以简称他为系统账号, ...

  2. 物联网操作系统Hello China移植mile stone之一:移植基础版本V1.76发布

    Hello China V1.76版发布,这是向ARM系列CPU移植的基础版本.相对V1.75版,该版本主要做了如下的一些调整: 1.  通过宏定义的方式对内核实现了模块化,开发者可以通过开启或关闭预 ...

  3. 计算CRC校验值(CRC16和CRC32)(网络传输检验)

    CRC有非常多的模式,我没有全部都做,目前支持 CRC16-Modbus CRC16-X25 CRC32 使用方法 auto data = QByteArray::fromHex( "01 ...

  4. WordPress主题制作教程8:自定义page模版

    创建新文件,头部注释 <?php /* Template Name: 新的page模版 */ ?> 在页面编辑右栏体现:

  5. JMS基本概念

    原文:http://blog.csdn.net/jiuqiyuliang/article/details/46701559 The Java Message Service (JMS) API is ...

  6. linux命令(4):ps命令

    Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信 ...

  7. Android 时间戳简单转化

    时间戳就是如1377216000000 这种格式我们在mysql数据库中会经常用到把时间转换成时间戳或把时间戳转换成日期格式了,下面我来介绍安卓中时间戳操作转换方法. 一.原理 时间戳的原理是把时间格 ...

  8. c# ffmpeg常用参数

    c#  ffmpeg常用参数 转换文件格式的同时抓缩微图: ffmpeg -i "test.avi" -y -f image2 -ss 8 -t 0.001 -s 350x240 ...

  9. 深入理解Java内存模型(四)——volatile

    volatile的特性 当我们声明共享变量为volatile后,对这个变量的读/写将会很特别.理解volatile特性的一个好方法是:把对volatile变量的单个读/写,看成是使用同一个监视器锁对这 ...

  10. CCNU-线段树练习题-A-单点更新1

    A - 单点更新1 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status Des ...