1、消息队列概念引入
消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值消息队列也有管道一样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI)
2、进程间通信数据结构
内核为每个进程间通信对象维护了一个数据结构
struct ipc_perm {
key_t __key; /* Key supplied to xxxget(2) */
uid_t uid; /* Effective UID of owner */
gid_t gid; /* Effective GID of owner */
uid_t cuid; /* Effective UID of creator */
gid_t cgid; /* Effective GID of creator */
unsigned short mode; /* Permissions */
unsigned short __seq; /* Sequence number */
};
消息队列在内核中的表示:
struct msqid_ds {
struct ipc_perm msg_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 of last msgsnd */
__kernel_ipc_pid_t msg_lrpid; /* last receive pid */
};
3、消息队列相关的函数
(1)msgget函数
函数原型:
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
int msgget(key_t key, int msgflag);
功能:
创建和访问一个消息队列。
参数:
参数一表示某个消息队列的名字
参数二表示权限设置为,一共有九个选项可供选择。
返回值:
成功返回一个非负整数,即消息队列的标号,失败返回-1
(2)msgctl函数
函数原型:
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能·:
消息队列的控制函数
参数:
参数一表示消息队列标识码
参数二表示将要采取的动作可以有三个选择,
IPC_STAT IPC_SET IPC_RMID IPC_INFO
参数三是一个结构体,
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 (non-standard) */
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) */
};
返回值:
成功返回0,失败返回-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);
功能:
把一条消息加到消息队列中
参数解释:
参数一:有msgget函数返回的消息队列标识码。
参数二:指针指向要发送的消息
参数三:消息长度
参数四:控制队列满时要发生的事情,msgflg = IPC_NOWAIT,当队列满时不等待,返回EAGAIN错误
返回值:
成功返回0,失败返回-1
说明:
1.消息结构在两方面受到制约:
首先,它必须小于系统规定的上限值;
其次,它必须以一个long int长整数开始,接收者函数将利用这个长整数确定消息的类型
2.消息结构参考形式如下:
struct msgbuf {
long mtype;
char mtext[1];
};
(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);
功能·:
从一个消息队列接收消息
参数解释:
参数一:由magget函数返回的消息队列的标号
参数二:指针,指向准备接收的消息
参数三:消息的长度
参数四:可以实现接收优先级的简单形式,
参数五:控制着队列中没有相应类型的消息可供做的事情
返回值:
成功返回实际放入缓冲区的字符个数,失败返回-1
说明:
msgtype=0返回队列第一条信息
msgtype>0返回队列第一条类型等于msgtype的消息
msgtype<0返回队列第一条类型小于等于msgtype绝对值的消息,并且是满足条件的消息类型最小的消息
msgflg=IPC_NOWAIT,队列没有可读消息不等待,返回ENOMSG错误。
msgflg=MSG_NOERROR,消息大小超过msgsz时被截断
msgtype>0且msgflg=MSG_EXCEPT,接收类型不等于msgtype的第一条消息。
实现代码:
server.c
client.c
comm.h
comm.c
运行结果:
这样就可以实现进程间不断的对话一样的数据交流。
使用ipcs -q命令可以看当前的所有消息队列,使用ipcrm -q msqid
删除消息队列