IPC----消息队列二.函数接口

  消息队列可以认为是一个消息链表,System V 消息队列使用消息队列标识符标识。具有足够特权的任何进程都可以往一个队列放置一个消息,具有足够特权的任何进程都可以从一个给定队列读出一个消息。在某个进程往一个队列写入消息之前,并不需要另外某个进程在该队列上等待消息的到达。System V 消息队列是随内核持续的,只有在内核重起或者显示删除一个消息队列时,该消息队列才会真正被删除。可以将内核中的某个特定的消息队列画为一个消息链表,如下图所示:

对于系统中每个消息队列,内核维护一个msqid_ds的信息结构:

struct msqid_ds {
    struct ipc_perm msg_perm;
    struct msg *msg_first;      /* first message on queue,unused  */
    struct msg *msg_last;       /* last message in queue,unused */
    __kernel_time_t msg_stime;  /* last msgsnd time */
    __kernel_time_t msg_rtime;  /* last msgrcv time */
    __kernel_time_t msg_ctime;  /* last change time */
    unsigned long  msg_lcbytes; /* Reuse junk fields for 32 bit */
    unsigned long  msg_lqbytes; /* ditto */
    unsigned short msg_cbytes;  /* current number of bytes on queue */
    unsigned short msg_qnum;    /* number of messages in queue */
    unsigned short msg_qbytes;  /* max number of bytes on queue */
    __kernel_ipc_pid_t msg_lspid;   /* pid of last msgsnd */
    __kernel_ipc_pid_t msg_lrpid;   /* last receive pid */
};

1.消息队列允许进程以消息的形式交换数据。读写都是针对整条消息,不能读写消息的一部分,不像管道那样可以以流的形式读写任意字节。

2.消息队列除了包含数据外,还有一个整数来表示该消息的类型。读取消息的时候即可以按照先进先出方式读取,也可以按照消息类型来读取。

接口函数

1.创建一个消息队列

 #include <sys/msg.h>
 #include <sys/types.h>
 #include <sys/ipc.h>

int msgget(key_t key, int msgflg);

key:是一个整数,该函数会将key转换成一个IPC标识符。

key有3种方法定义:

1)手动随意指定一个整数。

2)把IPC_PRIVATE当作key传入,系统会自动生成。

3)用ftok()函数。

注:参数key设置成常数IPC_PRIVATE并不意味着其他进程不能访问该消息队列,只意味着即将创建新的消息队列。

参数msgflg可以为以下:IPC_CREAT、IPC_EXCL、IPC_NOWAIT或三者的或结果。

调用返回:成功返回消息队列描述字,否则返回-1。

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

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

2.发送消息

 #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:用msget()获取的id。

mgsp:存储消息的结构指针,下面的mtype就是自定义的消息类型,mtext是消息数据。

struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[1];    /* message data */
           };

对发送消息来说,有意义的msgflg标志为IPC_NOWAIT,指明在消息队列没有足够空间容纳要发送的消息时,msgsnd是否等待。造成msgsnd()等待的条件有两种:

  • 当前消息的大小与当前消息队列中的字节数之和超过了消息队列的总容量;
  • 当前消息队列的消息数(单位"个")不小于消息队列的总容量(单位"字节数"),此时,虽然消息队列中的消息数目很多,但基本上都只有一个字节。

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

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

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

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

调用返回:成功返回0,否则返回-1。

功能:   该系统调用从msgid代表的消息队列中读取一个消息,并把消息存储在msgp指向的msgbuf结构中。

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

  1. 不满足上述两个条件,即消息队列中有容纳该消息的空间;
  2. msqid代表的消息队列被删除;
  3. 调用msgsnd()的进程被信号中断;

3.接收消息

#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指定msgbuf的mtext成员的长度(即消息内容的长度);

  msgtyp为请求读取的消息类型;即msgbuf里面的mtype。但还有别的用法:

如果为0,就获取队列中第一个可用消息。

大于0,获取相同类型消息的第一个,即mtype。

小于0,获取等于或小于mtype的绝对值的所有消息中最小的一个。

  读消息标志msgflg可以为以下几个常值的或:

  • IPC_NOWAIT 如果没有满足条件的消息,调用立即返回,此时,errno=ENOMSG
  • IPC_EXCEPT 与msgtyp>0配合使用,返回队列中第一个类型不为msgtyp的消息
  • IPC_NOERROR 如果队列中满足条件的消息内容大于所请求的msgsz字节,则把该消息截断,截断部分将丢失。

调用返回:成功返回读出消息的实际字节数,否则返回-1。

功能: 该系统调用从msgid代表的消息队列中读取一个消息,并把消息存储在msgp指向的msgbuf结构中。

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

  1. 消息队列中有了满足条件的消息;
  2. msqid代表的消息队列被删除;
  3. 调用msgrcv()的进程被信号中断;

4.消息控制

 #include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/msg.h>

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

cmd:有3个选项,IPC_STAT,IPC_SET,IPC_RMID。

  1. IPC_STAT:该命令用来获取消息队列信息,返回的信息存贮在buf指向的msqid_ds结构中;
  2. IPC_SET:该命令用来设置消息队列的属性,要设置的属性存储在buf指向的msqid结构中;可设置属性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes,同时,也影响msg_ctime成员。
  3. IPC_RMID:删除msqid标识的消息队列;

调用返回:成功返回0,否则返回-1。

例子程序见参考3

参考:

System V进程间通信—— 消息队列      http://blog.chinaunix.net/uid-22566367-id-1727281.html

System V IPC(1)-消息队列      http://www.cnblogs.com/yuuyuu/p/5133915.html

System V 消息队列        http://www.cnblogs.com/Anker/archive/2013/01/07/2848869.html

时间: 2024-10-12 23:57:41

IPC----消息队列二.函数接口的相关文章

Linux进程通信(二)IPC消息队列

一.什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的同步和阻塞问题.但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制. Linux用宏MSGMAX和MSGMNB来限制一条消息的最大长度和一个队列的最大长度MSGMNI来限制消息队列的总数. 二.IPC对象数据结构 内核为每个IPC对象维护一个数据结构(/usr/include/linux/ip

IPC——消息队列

Linux进程间通信——使用消息队列 下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信——使用命名管道 一.什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.消息队列是消息的链接表,存放在内核中并由消息队列标识符标识.  每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的同步和阻塞问题(命名管道要读端和写端

IPC 消息队列 一

消息队列可以认为是一个消息链表,某个进程往一个消息队列中写入消息之前,不需要另外某个进程在该队列上等待消息的达到,这一点与管道和FIFO相反.Posix消息队列与System V消息队列的区别如下:1. 对Posix消息队列的读总是返回最高优先级的最早消息,对System V消息队列的读则可以返回任意指定优先级的消息.2. 当往一个空队列放置一个消息时,Posix消息队列允许产生一个信号或启动一个线程,System V消息队列则不提供类似的机制. Posix消息队列操作函数如下: #includ

IPC: 消息队列

#################################################### 消息队列   消息队列分为: 1.posix消息队列:可以在同一主机上有亲缘关系或无亲缘关系的进程间使用. 2.system v消息队列:同上. 消息队列有随内核的持续性. ----------------------------------------------------------- posix消息队列: gcc -lrt #include <mqueue.h> #include

IPC——消息队列双向通行

消息队列提供了一个进程向另一个进程发送数据块的方法,每个数据块都被认为是有一个类型的,这个类型下文中是用常量is_client_snd和is_server_snd来表示的 消息队列相比管道来说的优点是避免了阻塞. 系统调用函数: #include<sys/types.h> #include<sys/ipc.h> 原型:key_t ftok(const char* pathname,int proj_id); 参数:pathname为一个已存在的.可获得信息的文件的全路径(必须是已经

Linux IPC 消息队列

1. Posix 消息队列 /* mq_open - open a message queue */#include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For mode constants */ #include <mqueue.h> mqd_t mq_open(const char *name, int oflag); mqd_t mq_open(const char *name, i

消息队列二三事

最近在看kafka的代码,就免不了想看看消息队列的一些要点:服务质量(QOS).性能.扩展性等等,下面一一探索这些概念,并谈谈在特定的消息队列如kafka或者mosquito中是如何具体实现这些概念的. 服务质量 服务语义 服务质量一般可以分为三个级别,下面说明它们不同语义. At most once 至多一次,消息可能丢失,但绝不会重复传输. 生产者:完全依赖底层TCP/IP的传输可靠性,不做特殊处理,所谓"发送即忘".kafka中设置acks=0. 消费者:先保存消费进度,再处理消

消息队列函数(msgget、msgctl、msgsnd、msgrcv)小记学习

一.什么是消息队列        消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的同步和阻塞问题.但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制. Linux用宏MSGMAX和MSGMNB来限制一条消息的最大长度和一个队列的最大长度. 二.在Linux中使用消息队列        Linux提供了一系列消息队列的函数接口来让我们方便地使用它来实现进程间的

Linux进程间通信 -- 消息队列 msgget()、msgsend()、msgrcv()、msgctl()

下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信 -- 使用命名管道 一.什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.  每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的同步和阻塞问题.但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制. Linux用宏MSGMAX和MSGMNB来限制一条