消息队列函数由msgget、msgctl、msgsnd、msgrcv四个函数组成。下面的表格列出了这四个函数的函数原型及其具体说明。

1.   msgget函数原型

msgget(得到消息队列标识符或创建一个消息队列对象)

所需头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

函数说明

得到消息队列标识符或创建一个消息队列对象并返回消息队列标识符

函数原型

int msgget(key_t key, int msgflg)

函数传入值

key

0(IPC_PRIVATE):会建立新的消息队列

大于0的32位整数:视参数msgflg来确定操作。通常要求此值来源于ftok返回的IPC键值

msgflg

0:取消息队列标识符,若不存在则函数会报错

IPC_CREAT:当msgflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的消息队列,则新建一个消息队列;如果存在这样的消息队列,返回此消息队列的标识符

IPC_CREAT|IPC_EXCL:如果内核中不存在键值与key相等的消息队列,则新建一个消息队列;如果存在这样的消息队列则报错

函数返回值

成功:返回消息队列的标识符

出错:-1,错误原因存于error中

附加说明

上述msgflg参数为模式标志参数,使用时需要与IPC对象存取权限(如0600)进行|运算来确定消息队列的存取权限

错误代码

EACCES:指定的消息队列已存在,但调用进程没有权限访问它

EEXIST:key指定的消息队列已存在,而msgflg中同时指定IPC_CREAT和IPC_EXCL标志

ENOENT:key指定的消息队列不存在同时msgflg中没有指定IPC_CREAT标志

ENOMEM:需要建立消息队列,但内存不足

ENOSPC:需要建立消息队列,但已达到系统的限制

如果用msgget创建了一个新的消息队列对象时,则msqid_ds结构成员变量的值设置如下:

Ÿ        msg_qnum、msg_lspid、msg_lrpid、 msg_stime、msg_rtime设置为0。

Ÿ        msg_ctime设置为当前时间。

Ÿ        msg_qbytes设成系统的限制值。

Ÿ        msgflg的读写权限写入msg_perm.mode中。

Ÿ        msg_perm结构的uid和cuid成员被设置成当前进程的有效用户ID,gid和cuid成员被设置成当前进程的有效组ID。

2.   msgctl函数原型

msgctl (获取和设置消息队列的属性)

所需头文件

#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_STAT:获得msgid的消息队列头数据到buf中

IPC_SET:设置消息队列的属性,要设置的属性需先存储在buf中,可设置的属性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes

buf:消息队列管理结构体,请参见消息队列内核结构说明部分

函数返回值

成功:0

出错:-1,错误原因存于error中

错误代码

EACCESS:参数cmd为IPC_STAT,确无权限读取该消息队列

EFAULT:参数buf指向无效的内存地址

EIDRM:标识符为msqid的消息队列已被删除

EINVAL:无效的参数cmd或msqid

EPERM:参数cmd为IPC_SET或IPC_RMID,却无足够的权限执行

3.   msgsnd函数原型

msgsnd (将消息写入到消息队列)

所需头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

函数说明

将msgp消息写入到标识符为msqid的消息队列

函数原型

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)

函数传入值

msqid

消息队列标识符

msgp

发送给队列的消息。msgp可以是任何类型的结构体,但第一个字段必须为long类型,即表明此发送消息的类型,msgrcv根据此接收消息。msgp定义的参照格式如下:

struct s_msg{ /*msgp定义的参照格式*/

     long type; /* 必须大于0,消息类型 */

           char mtext[256]; /*消息正文,可以是其他任何类型*/

    } msgp;

msgsz

要发送消息的大小,不含消息类型占用的4个字节,即mtext的长度

msgflg

0:当消息队列满时,msgsnd将会阻塞,直到消息能写进消息队列

IPC_NOWAIT:当消息队列已满的时候,msgsnd函数不等待立即返回

IPC_NOERROR:若发送的消息大于size字节,则把该消息截断,截断部分将被丢弃,且不通知发送进程。

函数返回值

成功:0

出错:-1,错误原因存于error中

错误代码

EAGAIN:参数msgflg设为IPC_NOWAIT,而消息队列已满

EIDRM:标识符为msqid的消息队列已被删除

EACCESS:无权限写入消息队列

EFAULT:参数msgp指向无效的内存地址

EINTR:队列已满而处于等待情况下被信号中断

EINVAL:无效的参数msqid、msgsz或参数消息类型type小于0

msgsnd()为阻塞函数,当消息队列容量满或消息个数满会阻塞。消息队列已被删除,则返回EIDRM错误;被信号中断返回E_INTR错误。

如果设置IPC_NOWAIT消息队列满或个数满时会返回-1,并且置EAGAIN错误。

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

①    不满足消息队列满或个数满两个条件,即消息队列中有容纳该消息的空间。

②    msqid代表的消息队列被删除。

③    调用msgsnd函数的进程被信号中断。

4.   msgrcv函数原型

msgrcv (从消息队列读取消息)

所需头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

函数说明

从标识符为msqid的消息队列读取消息并存于msgp中,读取后把此消息从消息队列中删除

函数原型

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,

int msgflg);

函数传入值

msqid

消息队列标识符

msgp

存放消息的结构体,结构体类型要与msgsnd函数发送的类型相同

msgsz

要接收消息的大小,不含消息类型占用的4个字节

msgtyp

0:接收第一个消息

>0:接收类型等于msgtyp的第一个消息

<0:接收类型等于或者小于msgtyp绝对值的第一个消息

msgflg

0: 阻塞式接收消息,没有该类型的消息msgrcv函数一直阻塞等待

IPC_NOWAIT:如果没有返回条件的消息调用立即返回,此时错误码为ENOMSG

IPC_EXCEPT:与msgtype配合使用返回队列中第一个类型不为msgtype的消息

IPC_NOERROR:如果队列中满足条件的消息内容大于所请求的size字节,则把该消息截断,截断部分将被丢弃

函数返回值

成功:实际读取到的消息数据长度

出错:-1,错误原因存于error中

错误代码

E2BIG:消息数据长度大于msgsz而msgflag没有设置IPC_NOERROR

EIDRM:标识符为msqid的消息队列已被删除

EACCESS:无权限读取该消息队列

EFAULT:参数msgp指向无效的内存地址

ENOMSG:参数msgflg设为IPC_NOWAIT,而消息队列中无消息可读

EINTR:等待读取队列内的消息情况下被信号中断

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

①    消息队列中有了满足条件的消息。

②    msqid代表的消息队列被删除。

③    调用msgrcv()的进程被信号中断。

消息队列使用程序范例

5.   消息队列控制范例

msgctl.c源代码如下:

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <sys/ipc.h>

#include <sys/msg.h>

#include <error.h>

#define TEXT_SIZE  512

struct msgbuf

{

long mtype ;

char mtext[TEXT_SIZE] ;

}  ;

int main(int argc, char **argv)

{

int msqid ;

struct msqid_ds info ;

struct msgbuf buf ;

struct msgbuf buf1 ;

int flag ;

int sendlength, recvlength ;

msqid = msgget( IPC_PRIVATE, 0666 ) ;

if ( msqid < 0 )

{

perror("get ipc_id error") ;

return -1 ;

}

buf.mtype = 1 ;

strcpy(buf.mtext, "happy new year!") ;

sendlength = sizeof(struct msgbuf) - sizeof(long) ;

flag = msgsnd( msqid, &buf, sendlength , 0 ) ;

if ( flag < 0 )

{

perror("send message error") ;

return -1 ;

}

buf.mtype = 3 ;

strcpy(buf.mtext, "good bye!") ;

sendlength = sizeof(struct msgbuf) - sizeof(long) ;

flag = msgsnd( msqid, &buf, sendlength , 0 ) ;

if ( flag < 0 )

{

perror("send message error") ;

return -1 ;

}

flag = msgctl( msqid, IPC_STAT, &info ) ;

if ( flag < 0 )

{

perror("get message status error") ;

return -1 ;

}

printf("uid:%d, gid = %d, cuid = %d, cgid= %d\n" ,

info.msg_perm.uid,  info.msg_perm.gid,  info.msg_perm.cuid,  info.msg_perm.cgid  ) ;

printf("read-write:%03o, cbytes = %lu, qnum = %lu, qbytes= %lu\n" ,

info.msg_perm.mode&0777, info.msg_cbytes, info.msg_qnum, info.msg_qbytes ) ;

system("ipcs -q") ;

recvlength = sizeof(struct msgbuf) - sizeof(long) ;

memset(&buf1, 0x00, sizeof(struct msgbuf)) ;

flag = msgrcv( msqid, &buf1, recvlength ,3,0 ) ;

if ( flag < 0 )

{

perror("recv message error") ;

return -1 ;

}

printf("type=%d, message=%s\n", buf1.mtype, buf1.mtext) ;

flag = msgctl( msqid, IPC_RMID,NULL) ;

if ( flag < 0 )

{

perror("rm message queue error") ;

return -1 ;

}

system("ipcs -q") ;

return 0 ;

}

编译 gcc msgctl.c –o msgctl。

执行 ./msg,执行结果如下:

uid:1008, gid = 1003, cuid = 1008, cgid= 1003

read-write:666, cbytes = 1024, qnum = 2, qbytes= 163840

------ Message Queues --------

key        msqid      owner      perms      used-bytes   messages

0x00000000 65536      zjkf       666        1024         2

type=3, message=good bye!

------ Message Queues --------

key        msqid      owner      perms      used-bytes   messages

6.  两进程通过消息队列收发消息

(1)发送消息队列程序

msgsnd.c源代码如下:

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <sys/ipc.h>

#include <sys/msg.h>

#include  <time.h>

#define TEXT_SIZE  512

struct msgbuf

{

long mtype ;

int  status ;

char time[20] ;

char mtext[TEXT_SIZE] ;

}  ;

char  *getxtsj()

{

time_t  tv ;

struct  tm   *tmp ;

static  char  buf[20] ;

tv = time( 0 ) ;

tmp = localtime(&tv) ;

sprintf(buf,"%02d:%02d:%02d",tmp->tm_hour , tmp->tm_min,tmp->tm_sec);

return   buf ;

}

int main(int argc, char **argv)

{

int msqid ;

struct msqid_ds info ;

struct msgbuf buf ;

struct msgbuf buf1 ;

int flag ;

int sendlength, recvlength ;

int key ;

key = ftok("msg.tmp", 0x01 ) ;

if ( key < 0 )

{

perror("ftok key error") ;

return -1 ;

}

msqid = msgget( key, 0600|IPC_CREAT ) ;

if ( msqid < 0 )

{

perror("create message queue error") ;

return -1 ;

}

buf.mtype = 1 ;

buf.status = 9 ;

strcpy(buf.time, getxtsj()) ;

strcpy(buf.mtext, "happy new year!") ;

sendlength = sizeof(struct msgbuf) - sizeof(long) ;

flag = msgsnd( msqid, &buf, sendlength , 0 ) ;

if ( flag < 0 )

{

perror("send message error") ;

return -1 ;

}

buf.mtype = 3 ;

buf.status = 9 ;

strcpy(buf.time, getxtsj()) ;

strcpy(buf.mtext, "good bye!") ;

sendlength = sizeof(struct msgbuf) - sizeof(long) ;

flag = msgsnd( msqid, &buf, sendlength , 0 ) ;

if ( flag < 0 )

{

perror("send message error") ;

return -1 ;

}

system("ipcs -q") ;

return 0 ;

}

(2)接收消息队列程序

msgrcv.c源代码如下:

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <sys/ipc.h>

#include <sys/msg.h>

#define TEXT_SIZE  512

struct msgbuf

{

long mtype ;

int  status ;

char time[20] ;

char mtext[TEXT_SIZE] ;

}  ;

int main(int argc, char **argv)

{

int msqid ;

struct msqid_ds info ;

struct msgbuf buf1 ;

int flag ;

int  recvlength ;

int key ;

int mtype ;

key = ftok("msg.tmp", 0x01 ) ;

if ( key < 0 )

{

perror("ftok key error") ;

return -1 ;

}

msqid = msgget( key, 0 ) ;

if ( msqid < 0 )

{

perror("get ipc_id error") ;

return -1 ;

}

recvlength = sizeof(struct msgbuf) - sizeof(long) ;

memset(&buf1, 0x00, sizeof(struct msgbuf)) ;

mtype = 1 ;

flag = msgrcv( msqid, &buf1, recvlength ,mtype,0 ) ;

if ( flag < 0 )

{

perror("recv message error\n") ;

return -1 ;

}

printf("type=%d,time=%s, message=%s\n", buf1.mtype, buf1.time,  buf1.mtext) ;

system("ipcs -q") ;

return 0 ;

}

(3)编译与执行程序

①    在当前目录下利用>msg.tmp建立空文件msg.tmp。

②    编译发送消息队列程序 gcc msgsnd.c -o  msgsnd。

③    执行./msgsnd,执行结果如下:

----- Message Queues --------

key        msqid      owner      perms      used-bytes   messages

0x0101436d 294912     zjkf       600        1072         2

④    编译接收消息程序 gcc msgrcv.c -o msgrcv

⑤    执行./msgrcv,执行结果如下:

type=1,time=03:23:16, message=happy new year!

------ Message Queues --------

key        msqid      owner      perms      used-bytes   messages

0x0101436d 294912     zjkf       600        536          1

⑥    利用ipcrm -q 294912删除该消息队列。因为消息队列是随内核持续存在的,在程序中若不利用msgctl函数或在命令行用ipcrm命令显式地删除,该消息队列就一直存在于系统中。另外信号量和共享内存也是随内核持续存在的。

摘录自《深入浅出Linux工具与编程》

转自:http://blog.csdn.net/guoping16/article/details/6584024

消息队列函数(msgget、msgctl、msgsnd、msgrcv)及其范例的更多相关文章

  1. 进程间通信系列 之 消息队列函数(msgget、msgctl、msgsnd、msgrcv)及其范例

    进程间通信系列 之 概述与对比   http://blog.csdn.net/younger_china/article/details/15808685  进程间通信系列 之 共享内存及其实例   ...

  2. 获取和设置消息队列的属性msgctl,删除消息队列

    消息队列的属性保存在系统维护的数据结构msqid_ds中,用户可以通过函数msgctl获取或设置消息队列的属性. int msgctl(int msqid, int cmd, struct msqid ...

  3. POSIX和SYSTEM的消息队列应该注意的问题

    首先看看POSIX的代码: 1.posix_mq_server.c #include <mqueue.h>#include <sys/stat.h>#include <s ...

  4. 第二十五章 system v消息队列(一)

    IPC对象的持续性 随进程持续 :一直存在直到打开的最后一个进程结束.(如pipe和FIFO) 随内核持续 :一直存在直到内核自举(内核自举就是把主引导记录加载到内存,并跳转执行这段内存)或显示删除( ...

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

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

  6. system的消息队列实例

    1\创建或打开消息队列函数原型:int msgget(key_t key, int msgflg)参数第一个参数为ftok方法创建的一个kety_t或者为一个整数值第二个参数为逻辑控制,IPC_CRE ...

  7. POSIX 消息队列 之 概述 链接方式

    NAMEmq_overview —— POSIX消息队列概述 DESCRIPTIONPOSIX消息队列允许进程以消息的形式交换数据.此API与System V消息队列(msgget(2),msgsnd ...

  8. Linux进程间通信(七):消息队列 msgget()、msgsend()、msgrcv()、msgctl()

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

  9. 消息队列实现回射客户/服务器和 msgsnd、msgrcv 函数

    一.msgsnd 和 msgrcv 函数 #include <sys/types.h>   #include <sys/ipc.h>   #include <sys/ms ...

随机推荐

  1. 51nod 1009 数位dp入门

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1009 1009 数字1的数量 基准时间限制:1 秒 空间限制:13107 ...

  2. PhantomJS 和Selenium模拟页面js点击

    由于自己不怎么会javascripts,无法找全所有的参数进行模拟提交,所以只能寻求Selenium和PhantpmJS的方式. 先说下ubuntu上怎么安装相应的环境,尤其PhantomJS安装比较 ...

  3. poj1469

    题解: 二分图匹配 然后判断最大匹配是否是m 代码: #include<cstdio> #include<cmath> #include<algorithm> #i ...

  4. 日志分析命令awk基础用法

    awk awk是一个很好用的文本处理工具,相对于sed常用用作一整行的处理,awk则比较擅长将一行分成数个字段来处理.而在我们性能测试中,可以awk可以帮助我们造数,也可以帮助我们分析日志. 简单来说 ...

  5. 多线程实现方式---实现Runnable接口

    多线程实现方式---实现Runnable接口 一个类如果需要具备多线程的能力,也可以通过实现java.lang.Runnable接口进行实现.按照Java语言的语法,一个类可以实现任意多个接口,所以该 ...

  6. OC-通知+Block

    =================================== 一.通知(NSNotification) NSNotification 通知类,这个类中有 NSNotificationCent ...

  7. Ruby on Rails入门——macOS 下搭建Ruby Rails Web开发环境

    这里只介绍具体的过程及遇到的问题和解决方案,有关概念性的知识请参考另一篇:Ruby Rails入门--windows下搭建Ruby Rails Web开发环境 macOS (我的版本是:10.12.3 ...

  8. Android OpenCSV

    OpenCSV https://sourceforge.net/projects/opencsv/ 使用参考 http://stackoverflow.com/questions/16672074/i ...

  9. opencv 识别答题卡

    参考这个网站,然后自己 找了张图片试了一下 http://blog.csdn.net/cp562090732/article/details/47804003 // test.cpp : 定义控制台应 ...

  10. OpenCV获取RTSP解码播放

    #include <opencv2/opencv.hpp> int main(int argc, char **argv){ IplImage *pFrame = NULL, *srcIm ...