软硬件环境
- ubuntu 16.04 64bit
简介
消息队列是系统内核提供的一个用来保存消息的队列,是进程间通信的一种常用方法
相关数据结构
1、msgbuf
struct msgbuf
{
long mtype; /*消息类型*/
char mtext[1]; /*消息内容*/
}
mtext
不受其描述的限制,实际上mtext
不仅可以保存字符,而且能保存任何形式的数据。因此程序员可以重新定义结构
struct mymsgbuf{
long mtype; /*消息类型*/
long request_id; /*请求标识符*/
struct client info; /*客户消息结构*/
};
需要注意的一点是,linux
系统对消息类型的最大升序有所限制,在/usr/include/linux/msg.h
中。
define MSGMAX 8192
2、msqid_ds
struct msqid_ds
{
struct ipc_perm msg_perm; /*消息队列的存取权限及其它一些信息,参见`ipc_perm`/
struct msg msg_first; /*first message on queue,unused*/
struct msg msg_last; /*last message in queue,unused*/
__kernel_time_t msg_stime; /* last msgsnd time*/
__kernel_time_t msg_rtime; /*last msgrcv time*/
__kernel_time_t msg_ctime; /*last change time*/
unsigned long msg_lcbytes; /*Reuse junk fields for 32 bit*/
unsigned long msg_lqbytes; /*ditto*/
unsigned short msg_cbytes; /*current number of bytes on queue*/
unsigned short msg_qnum; /*number of messages in queue*/
unsigned short msg_qbytes; /*max number of bytes on queue*/
__kernel_ipc_pid_t msg_lspid; /*最近一次向队列发送消息的进程的pid*/
__kernel_ipc_pid_t msg_lrpid; /*最近一次从队列中取出的消息的进程的pid*/
};
3、msg
struct msg
{
struct msg msg_next; /*消息链表中的再一节点指针*/
long msg_type; /*和结构msgbuf中的mtype一样*/
char msg_spot; /*消息内容,和msgbuf中的mtext一样*/
time_t msg_stime; /*msgsnd time*/
short msg_ts; /*消息长度*/
};
4、ipc_perm
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;
};
这个结构用来保存每个IPC
对象的权限信息
相关函数
1、ftok()
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
ftok()
通过混合pathname
所指文件的inode
和minor device
的值以及proj_id
的值来产生关键字,示例
key_t key;
key = ftok(".","a"); //程序在同一目录下运行
2、msgget()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
msgget()
用来创建新的消息队列或者获取已有的消息队列。其中key
是消息队列的关键字,用它来和已有的消息队列对象的关键字进行比较来判断消息队列是否已经创建,msgflg
可取如下值
-
IPC_CREAT
: 如果消息队列不存在,则创建,否则打开 -
IPC_EXCL
: 与IPC_CREAT
一起使用,IPC_CREAT | IPC_EXCL
,如果消息队列不存在,则创建,否则返回错误除此以外,在
msgflg
中还可以和存取权限结合使用
msgget()
返回新建的消息队列对象的标识符,如果队列已经存在,返回-1
3、msgsnd()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgsnd()
用来向消息队列发送消息。msgid
是消息队列对象的标识符(由msgget()
得到),msgp
指向消息所在的内存,msgsz
是消息长度,msgsz = sizeof(struct mymsgbuf) - sizeof(long)
;
msgflg
可取如下值
IPC_NOWAIT
: 如果队列已满,消息不再写入队列,控制权返回调用函数的进程。如果不指定,进程将被阻塞直到消息可以被写入- 0 : 忽略标志位
4、msgrcv()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
msgrcv()
用来从消息队列中取出消息。msgtype
指定从消息队列中所取的消息的类型,如果msgtype
为0,则不做类型检查直接返回队列中最旧的消息。
msgflg
可以取如下值
-
IPC_NOWAIT
: 如果消息队列为空,返回ENOMSG
,控制权交给调用函数的进程,如果不指定这个参数,进程将被阻塞直到可以从队列中取出符合条件的消息为止。如果一个client
正在等待的队列被删除,返回EIDRM
。如果进程在阻塞等待过程中收到系统的中断信号,则返回EINTR
-
MSG_NOERROR
: 如果函数取得的消息长度大于msgsz
,将只返回msgsz
长度的信息,剩余部分被丢弃。如果不指定这个参数,返回E2BIG
,消息不被取出 -
0 : 忽略标志位
5、msgctl()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msgctl()
用来控制消息队列的行为。参数cmd
是可对消息队列进行的操作
IPC_STAT
: 取出消息队列的msqid_ds
数据,并存入buf
中IPC_SET
: 设置消息队列的msqid_ds
结构中的msg_perm
成员,设定的值由buf
指向的msqid_ds
结构给出IPC_EMID
: 将队列从内核中删除