2019-10-8IPC之消息队列

IPC之消息队列

概念:

消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息。消息队列是随内核持续的。

系统V消息队列是随内核持续的,只有在内核重起或者显示删除一个消息队列时,该消息队列才会真正被删除。因此系统中记录消息队列的数据结构(struct ipc_ids msg_ids)位于内核中,系统中的所有消息队列都可以在结构msg_ids中找到访问入口。 消息队列就是一个消息的链表。每个消息队列都有一个队列头,用结构struct msg_queue来描述。队列头中包含了该消息队列的大量信息,包括消息队列键值、用户ID、组ID、消息队列中消息数目等等,甚至记录了最近对消息队列读写进程的ID。读者可以访问这些信息,也可以设置其中的某些信息。

相信看到这里的应该都知道pipe,我们来简单看看它们的优缺点:

优点和缺点

优点:

消息队列是两个不相关进程之间传递数据的有效渠道.

与命名管道相比,具有的优势是:
独立于发送以及接收进程而存在;
消除命名管道的打开以及关闭而存在的困难;
可以提前查看紧急信息;
避免命名管道的同步以及阻塞问题;
缺点:
与命名管道一样,每个数据块都有一个最大长度限制;
系统中所有队列包含的全部数据块长度也有一个上限;

msgmni 最大消息队列数 16
msgmax 最大消息长度(字节数) 8192
msgmnb 消息队列中的最大字节数 16384

如果想查看系统的消息队列,共享内存,信号量,可以用命令: ipcs

结构:

接下来2张图帮助大家更好理解内核中消息队列的结构:

在这里插入图片描述
在这里插入图片描述

IPC机制都会有这个对象
拥有者及权限对象		
struct ipc_perm
{
	__kernel_key_t	key;   
	__kernel_uid_t	uid;
	__kernel_gid_t	gid;
	__kernel_uid_t	cuid;
	__kernel_gid_t	cgid;
	__kernel_mode_t	 mode; 
	unsigned short	seq;
};
	用于管理消息队列的对象
	struct msqid_ds {
	   struct ipc_perm msg_perm;     /* Ownership and permissions */
	   time_t          msg_stime;    /* Time of last msgsnd(2) */
	   time_t          msg_rtime;    /* Time of last msgrcv(2) */
           time_t          msg_ctime;    /* Time of last change */
	   unsigned long   __msg_cbytes; /* Current number of bytes in
	                                    queue (nonstandard) */
	   msgqnum_t       msg_qnum;     /* Current number of messages
	                                    in queue */
	   msglen_t        msg_qbytes;   /* Maximum number of bytes
	                                    allowed in queue */
	   pid_t           msg_lspid;    /* PID of last msgsnd(2) */
	   pid_t           msg_lrpid;    /* PID of last msgrcv(2) */
	   struct msg *    msq_first ;
 	   struct msg *    msq_last ;
	};

相关函数:

1.获取key

  • key:通信双方约定好的KEY值,32位的整形数据
  • id :系统会为IPC分配一个唯一的ID,通信双方都需要知道ID才能使用当前IPC方法,创建者会返回当前ID值,
 	#include <sys/types.h>
  	#include <sys/ipc.h>
	key_t ftok(const char *pathname, int proj_id);	//将文件的索引节点号取出,前面加上子序号得到key_t的返回值。
	
    .  proj_id 		子序列号
    key 31-24 proj_id 低8位
	key 23-16 st_dev属性的低8位
	key 15-0  st_ino属性的低16位

2.创建消息队列(创建struct msqid_ds对象)

原型:int msgget(key_t key, int msgflg )

返回值:失败返回-1, 个数限制, 打开别人队列没权限。大于0 调用成功 返回已打开的消息队列ID标识。

参数:

key_t key //相当于文件名,由函数ftok生产

int msgflg //指定消息队列创建。一般是IPC_CREAT 0644 或者0 (为0 则代表由操作系统自动选择)

		IPC_CREAT  找到当前的key对应的IPC,如果没有IPC则进行创建
		IPC_EXCL   如果存在则返回失败
		IPC_NOWAIT  返回值为当前ipc对应的id值 

3.设置对象
原型:int msgctl(int msqid,int cmd, struct msqid_ds *buf)
参数:

​ cmd:

	IPC_RMID  删除 
	IPC_SET  设置ipc_perm参数 
	IPC_STAT 获取ipc_perm参数
	IPC_INFO 获取ipc信息  和ipcs

4.使用对象
在这里插入图片描述

参数:

​ void* msgp: //想写入消息队列数据的地址,是指向消息缓冲区的指针,此位置用来暂时存储发送接收消息,是一个用户可定义的通用结构,形态如下:

struct msgbuf
{

  long mtype;       //k接收类型,可看作消息队列通道号channel   ,同时必须> 0

  char mtext[100]   //存放内容
};

​ size_t msgsz //消息大小, 不算上通道号大小

gbuf
{

long mtype; //k接收类型,可看作消息队列通道号channel ,同时必须> 0

char mtext[100] //存放内容
};


​	size_t msgsz   //消息大小, 不算上通道号大小

   int msgflg     //一般输入0,由操作系统自行选择
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值