tlpi: System V 消息队列

本文介绍了System V消息队列的使用,包括创建/打开、发送、接收消息及队列控制。通过msgget()、msgsnd()、msgrcv()和msgctl()系统调用进行操作,讲解了各种参数的意义和使用场景,强调了消息通信的面向消息特性及非阻塞选项。
摘要由CSDN通过智能技术生成

Syetem V消息队列

System V消息队列的一些基本特征

  • 通过消息队列进行的通信是面向消息的,即读者接收到有写者写入的整条消息,读取消息的一部分或者一次读取多条消息的操作都是做不到的
  • 每条消息包含有一个用整数表示的类型,可以根据顺序读取消息,也可以根据消息的类型读取消息
1.创建/打开一个消息队列

msgget()用于创建一个新消息队列或者用于获取一个已有的消息队列

#include<sys/types.h>
#include<sys/msg.h>
int msgget(key_t key, int msgflg);
					//成功:返回0 失败:返回 -1

参数解释:

  • key

    用于生成/获取消息队列的键,可由IPC_PRIVATE或者ftok()产生

  • msgflg

    用于指定新生成的消息队列的权限,或者检查一个已有的消息队列的权限

    有以下取值

    描述
    IPC_CREAT如果没有指定的key对应的消息队列,那么就创建一个新队列
    IPC_EXCL与IPC_CREAT搭配使用,用于创建新队列
2.发送消息

msgsnd()用于向消息队列发送消息

#include <sys/types.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgz, int msgflg);
							//成功:返回 0  失败:返回-1

参数解释:

  • msqid

    消息队列标识符

  • msgp

    msgp是一个指向自定义结构体的指针,该结构体通常被定义成如下形式

    struct mymsg{
    	long mtype;    //消息类型
    	char mtext[];  //消息文本
    }
    
    • 当使用msgsnd()发送消息时,mtype字段必须大于0
  • msgz

    指定了msgp所指结构体的mtext[]字段大小

  • msgflg

    有如下取值

    • IPC_NOWAIT

      执行一个非阻塞的发送操作,通常情况下,当消息队列已满时,发送操作会陷入阻塞,如果指定IPC_NOWAIT标志后,则会在队列满并且发送消息时立即返回EAGAIN错误

3.接受消息

msgrcv()系统调用从消息队列中读取(并且删除)一条消息并且复制到msgp所指向的缓冲区

#include <sys/types.h>
#include <sys/msg.h>
ssize_t msgrcv(int msgid, void*msgp, size_t maxmsgz, long msgtyp, int msgflg);
					//成功:返回读取到mtext的字节数  失败:返回-1

参数解释

  • msgid

    消息队列标识符

  • msgp

    指向消息队列缓冲区

  • maxmsgz

    表明msgp缓冲区中mtext字段的最大可用空间,如果消息队列中待删除的消息体的大小超过了maxmsgsz字节,那么就不会从消息队列中删除消息(除非指定了MSG_NOERROR)标志

  • msgtyp

    根据该参数指定如果读取消息队列中的消息

    • msgtyp 等于0

      删除队列中的第一条消息并将其返回给调用进程

    • msgtyp大于0

      将队列中第一条mtype等于msgtyp的消息删除并将其返回给调用进程,通常将msgtyp指定为进程pid

    • msgtyp小于0

      将队列中mtype最小并且其值小于或等于msgtyp的绝对值的第一条消息删除并返回给调用进程

  • msgflg

    有以下取值

    • IPC_NOWAIT

      非阻塞,当队列中没有匹配msgtyp的消息时不阻塞而是立即返回ENOMSG

    • MSG_EXCEPT

      只有当msgtyp大于0时这个标记才会有作用,将消息队列中第一条mtype不等于msgtyp的消息删除并返回给调用者

      该标记为Linux特有,并且需要指定_GNU_SOUORCE

    • MSG_NOERROR

      如果消息的mtext字段大小超过了可用空间,那么指定该字段后,将会从队列中删除消息并且将mtext字段的大小截断

      为maxmsgsz字节

msgsnd(),msgrcv()与信号

当msgsnd()/msgrcv()发生阻塞时,它们有可能被信号处理器中断,当发生这种情况时,msgsnd()/msgrcv()总是会返回EINTR错误,

即使信号处理器设置了SA_RESTART标志,调用也不会重启

4.消息队列控制

msgctl()系统调用在标识符为msqid的消息队列上执行控制操作

#include <sys/types.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
									//成功:返回0  失败:返回-1

cmd参数可以取如下值

在这里插入图片描述

5.消息队列关联数据结构

每个消息队列都有一个与之相关的数据结构

struct msqid_ds {
	struct ipc_perm msg_perm;             //所有权以及权限
	time_t          msg_stime;			  //上一次msgsnd()的时间
	time_t          msg_rtime;			  //上一次msgrcv()的时间
	time_t          msg_ctime;			  //上一次状态改变的时间
	unsigned long   __msg_cbytes;		  //队列中的字节总数
	msgqnum_t       msg_qnum;			  //队列中的消息总数
	msglen_t        msg_qbytes;			  //队列所能容纳的最大字节数
	pid_t           msg_lspid;            //上一次使用msgsnd()的进程
	pid_t           msg_lrpid;            //上一次使用msgrcv()的进程
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值