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

一、什么是消息队列
        消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。

Linux用宏MSGMAX和MSGMNB来限制一条消息的最大长度和一个队列的最大长度。

二、在Linux中使用消息队列
        Linux提供了一系列消息队列的函数接口来让我们方便地使用它来实现进程间的通信。消息队列函数由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()的进程被信号中断。

原文地址:https://www.cnblogs.com/AlexBai/p/9551661.html

时间: 2024-08-30 08:15:54

消息队列函数(msgget、msgctl、msgsnd、msgrcv)小记学习的相关文章

消息队列函数

1.消息队列结构体的定义 typedef struct{        uid_t   uid;   /* owner`s user id */        gid_t   gid;    /* owner`s group id */        udi_t   cuid;   /* creator`s user id */        gid_t   cgid;   /* creator`s group id */        mode_t  mode;   /* read-write

系统学习消息队列分享(一) 怎样系统学习消息队列?

从系统之间有通信需求开始呢,就产生了消息队列,它也是最古老的中间件之一.它的应用场景非常广泛,分布式系统中的很多进程间通信问题,都可以用消息队列来解决.可以说消息队列是所有后端程序员的必备技能.但是,想要系统.深入地学习消息队列,却并不容易. 要了解消息队列的完整知识体系,想深度进阶为消息队列达人,从理论到实践,从基础到进阶,从深度到广度,全方位吃透消息队列. 哪些人适合学消息队列? 后端开发者:消息队列几乎是每个后端程序员都会用到的中间件,无论你是开发微服务,实时计算,还是机器学习程序,都需要

消息队列 链接

NAMEmq_overview —— POSIX消息队列概述 DESCRIPTIONPOSIX消息队列允许进程以消息的形式交换数据.此API与System V消息队列(msgget(2),msgsnd(2),msgrcv(2)等)有明显不同,但做的事情差不多. 消息队列通过mq_open(3)创建和打开,此函数返回一个消息队列描述符(mqd_t),它用于之后的调用中引用打开的消息队列.每个消息队列由一个名字标识,该名字具有这样的格式/somename,亦即,一个空字符结尾,以斜线开头,最多跟着N

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

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

XSI进程间通信-----消息队列

1. 基本特点 1) 消息队列是一个由系统内核负责存储和管理,并通过消息队列标识引用的数据链表,消息队列 和有名管道fifo的区别在: 后者一次只能放一个包,而前者则可以放很多包,这样就能处理发包快,哪包慢的问题 2) 可以通过msgget函数创建一个新的消息队列, 或获取一个已有的消息队列. 通过msgsnd函数 (send)向消息队列的后端追加消息, 通过msgrcv(receive)函数从消息队列的前端提取消息. 3) 消息队列中的每个消息单元除包含消息数据外,还包含消息类型和数据长度.消

消息队列状态:struct msqid_ds

Linux的消息队列(queue)实质上是一个链表, 它有消息队列标识符(queue ID). msgget创建一个新队列或打开一个存在的队列; msgsnd向队列末端添加一条新消息; msgrcv从队列中取消息, 取消息是不一定遵循先进先出的, 也可以按消息的类型字段取消息. 1. 标识符(des)和键(key): 消息队列, 信号量和共享存储段, 都属于内核中的IPC结构, 它们都用标识符来描述. 这个标识符是一个非负整数, 与文件描述符不同的是, 创建时并不会重复利用通过删除回收的整数,

进程间通信之消息队列通信

概念 消息队列 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法 每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值 消息队列也有管道一样的不足,就是每条消息的最大长度是有上限的(MSGMAX),每个消息队列的总字节数(内核缓冲上限)是有上限的(MSGMNB),系统上消息队列的总数(消息条目数)也有一个上限(MSGMNI) 对比: 管道 消息 流管道 有边界 先进先出 可以后进入.先出来 消息大小三大限制 cat /proc/sys/kernel/msgmax最

消息队列的实现

消息队列  ----  双向通信(读取不一定先入先出) 1. 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 每个数据块都被认 为是有一个类型,接收者进程接收的数据块可以有不同的类型值.我们可以通过发送消息 来避免命名管道的同步和阻塞问题. 消息队列与管道不同的是,消息队列是基于消息的,而管道是基于字节流的,且消息队列的读取不一定是先入先出. 2.消息队列的结构: struct ipc_perm  {     key_t      _key;         /* Key sup

消息队列、信号量、共享存储

消息队列.信号量.共享存储是IPC进程间通信的三种形式,它们功能不同,但有一些相似点,下面先介绍它们相类似的特征,然后再逐一说明. 1.相似点 每个内核中的IPC结构(消息队列.信号量.共享存储)都用一个非负整数的标识符加以引用,与文件描述符不同,当一个IPC结构被创建,以后又被删除时,与这种结构相关的标识符连续加1,直至达到一个整型数的最大正直,然后又回转到0.标识符是IPC对象的内部名,还有一个外部名称为键,数据类型是key_t,用于多个合作进程能够在同一IPC对象上会合,键由内核转换成标识