linux 消息队列API

一. 什么是linux的消息队列:

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

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

二.LInux中使用消息队列

linux提供一系列消息队列的函数接口来让我们方便地使用它来实现进程间的通信。消息队列函数有
msgget,msgctl,msgsnd,msgrcv四个函数组成。

1.msgget函数:创建队列,返回队列的句柄

#include 
#include 
#include 
函数原型:int msgget(key_t key,int msgflag);
	key:0(IPC_PRIVATE):会建立新的消息队列。
		大于032位整数:视参数msglag来确定操作。通常要求此值来源于ftok返回的IPC键值
	
	msgflag: 0消息队列标识符,若不存在则函数会报错。
			 IPC_CREAT:当msgflag&IPC_CREAT为真时,如果内核中不存在键值与key相等的消息队列,则新建
			 一个消息队列;如果存在这样的消息队列,返回此消息队列的标识符。
			 IPC_CREAT|IPC_EXCL:如果内核中不存在键值与key相等的消息队列,则新建一个消息队列,如果
			 存在这样的消息队列则报错。
	返回:成功:返回消息队列的标识符,出错:-1,消息原因存在与error中
	
> 备注说明:上述msgflg参数为模式标志参数,使用时需要与IPC对象存取权限如(0666)进行|运算来确定消息队列的存取权限。
错误代码:
	EACCES:指定消息队列已存在,但调用进程没有权限访问他。
	EEXIST:key指定的消息队列已存在,而msgflg中同时指定IPC_CREAT和IPC_EXCL标志
	ENOENT:key指定的消息队列不存在同时msgflg中没有指定IPC_CREAT标志
	ENOMEM:需要建立消息队列,但内存不足。
	ENOSPC:需要建立消息队列,但是达到了系统限制

2.msgctl函数:设置和获取队列的属性(后续补充)

	int msgctl(int msqid, int cmd, struct msqid_ds *buf);
	msgid:消息队列的句柄标识符。
	cmd:IPC_STAT:获得msgid的消息队列头数据到buf中
		 IPC_SET:设置消息队列的属性,要设置的属性需先存储在buf中,可设置的属性包括:
		 msg_perm.uid,
		 msg_perm.gid,
		 msg_perm.mode 
		 msg_qbytes;

3.msgsnd函数:将消息写入到消息队列中

int msgsnd(int msgid,const void* msgp,size_t msgsz,int msgflg);
	msgid:消息队列的句柄标识符。
	msgp:发送给队列的消息。
		msgp可以是任何类型的结构体,<<<但第一个字段必须为long类型,即表明此发送消息的类型 !!!>>>,
		msgrcv根据此接收消息。msgp定义的参照格式如下:
	    struct s_msg
	    { /*msgp定义的参照格式*/
	    	 long type; /* 必须大于0,消息类型 */
	         char mtext[256]; /*消息正文,可以是其他任何类型*/
	    }msgp;
	
	msgze:要发送消息的带下,不含消息类型占用的4个字节,即mtex的长度。
	
	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()解除阻塞的条件有以下三个条件:
	1.不满足消息队列满或个数满两个条件,即消息队列中有容纳该消息的空间。
	2.msqid代表的消息队列被删除。
	3.调用msgsnd函数的进程被信号中断。

4.msgrcv函数:从消息队列中读取消息

 size_t msgrcv(int msgid,void* msgp,size_t msgsz,long msgtyp,int msgflg);
 	msgid:消息队列标识符
 	msggp:存放消息的结构体,结构体类型要与msgsnd函数发送的消息类型相同。
 	msgze:要接收消息的大小,不含消息类型占用的4个字节。
 	msgtyp:
 		0:接收第一个消息。
 		>0: 接收类型等于msgtyp的第一个消息
 		<0:接收类型等于或者小于msgtype绝对值的第一个消息
 	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()解除阻塞的条件有以下三个:
		1:消息队列中有了满足条件的消息。
		2:msqid代表的消息队列被删除。
		3:调用msgrcv()的进程被信号中断。

你可能感兴趣的:(linux,嵌入式硬件)