一、    概念

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

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. GDB调试方法精粹

    http://blog.chinaunix.net/uid-26922071-id-3756018.html 一.多线程调试 1. 多线程调试,最重要的几个命令: info threads       ...

  2. QT5.3无法自动调用incomingConnection函数的问题(4.7没有这个问题)

    最近将qt4.7的一个工程移到5.3,遇到了几个麻烦事,主要是这个incomingConnection监听后无法自动调用的问题,在4.7上是完全没有问题的,到了5.3就不行,网上也查了下,网友们都是放 ...

  3. logback与Log4J的区别

    原文:http://blog.csdn.net/lwzcjd/article/details/5617200 Logback和log4j是非常相似的,如果你对log4j很熟悉,那对logback很快就 ...

  4. swift:创建九宫格

    九宫格的创建是有规律可循的,每一个格子的水平和竖直方向的间隔是固定的,通过计算每一个格子的位置,然后把它们依次放到视图中即可. 一般的步骤为: 1.设置格子的总个数和每一列的格子数 2.求格子的间隔: ...

  5. powerdesigner jdbc 连接 oracle

    实验环境: powerdesigner 15 oracle 11g jdk1.6.0_43 提示:jdk必须选择32位,64位会报  "Could not Initialize JavaVM ...

  6. WordPress搭建Personal Blog 个人博客

    早就想搭建一个专属于自己的博客了,用来记录自己生活.学习的点点滴滴.之所以选WordPress,主要是因为它可以支持Latex,而且特别喜欢其简约的风格. WordPress有个the famous ...

  7. Android init.rc解析【转】

    转自:http://www.linuxidc.com/Linux/2014-10/108438.htm 本文主要来自$Android_SOURCE/system/init/readme.txt的翻译. ...

  8. AngularJs-ui modal 传参数

    最近开始学习 AnjularJs: 看了两天项目的代码开始动手完成项目中的功能,碰到些问题记录下备忘:方便以后再碰到这样疑惑的coder. 参见 Angular-ui  modal 传递 header ...

  9. Oracle Order Management DropShip Flow for R12

    Oracle Order Management DropShip Flow for R12 Email ThisBlogThis!Share to TwitterShare to FacebookSh ...

  10. android 开发如何做内存优化

    不少人认为JAVA程序,因为有垃圾回收机制,应该没有内存泄露.其实如果我 们一个程序中,已经不再使用某个对象,但是因为仍然有引用指向它,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造 ...