从一个进程向另外一个进程发送一个带有类型的数据块
是存储在内核中的一个消息的队列(链表)
查看消息队列:ipcs -q
IPC对象数据结构:/usr/include/linux/ipc.h
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;
};
消息队列结构:/usr/include/linux/msg.h
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 */
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 */
__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 */
};
消息队列的系统限制:
#define MSGMNI 16 /* <= IPCMNI */ /* max # of msg queue identifiers */
#define MSGMAX 8192 /* <= INT_MAX */ /* max size of message (bytes) */
#define MSGMNB 16384 /* <= INT_MAX */ /* default max size of a message queue */
消息队列结构:
消息结构:
struct msgbuf {
long mtype; /* type of message */
char mtext[1]; /* message text */
};
创建或访问一个消息队列
key:内核中消息队列的标识
msgflg:
IPC_CREAT 不存在则创建,存在则打开
IPC_EXCL 与IPC_CREAT同时使用,存在则报错
mode 权限
从消息队列接收消息
成功后内核更新与该消息队列相关联的 msgid_ds 结构,刷新调用进程ID(msg_lrpid)、调用时间(msg_rtime)、并将消息数减1(msg_qnum)
msqid:由msgget返回的消息队列ID
msgp:指向准备接收的消息结构体msgbuf,需要自己定义
msgsz:msgp指向的要接收的数据长度,不包含msgtype
msgtype:指定接收的数据类型
msgflg:标志选项
类似于 ioctl 垃圾桶函数
cmd
通过文件的inode节点号和一个proj_id计算出一个key值
缺点:如果文件被删除或替换生,通过key值打开的不是同一个msgqueue
client.c
#include
#include
#include
#include
#include
#include
#include
#include
#define IPC_KEY 0x12345678 //消息队列key
#define TYPE_SER 1 //数据块类型
#define TYPE_CLI 2 //数据块类型
struct msgbuf {
long mtype;
char mtext[1024];
};
int main()
{
int msgid = -1;
msgid = msgget(IPC_KEY, IPC_CREAT | 0664);
if (msgid < 0) {
perror("msgget error");
return -1;
}
while (1) {
//接收数据
//struct msgbuf 自己定义
struct msgbuf buf;
//msgid :操作句柄
msgrcv(msgid, &buf, 1024, TYPE_CLI, 0);
printf("client say:[%s]\n", buf.mtext);
//发送数据
memset(&buf, 0x00, sizeof(struct msgbuf));
buf.mtype = TYPE_SER;
scanf("%s", buf.mtext);
msgsnd(msgid, &buf, 1024, 0);
}
//删除IPC
msgctl(msgid, IPC_RMID, NULL);
return 0;
}
server.c
#include
#include
#include
#include
#include
#include
#include
#include
#define IPC_KEY 0x12345678 //消息队列key
#define TYPE_SER 1 //数据块类型
#define TYPE_CLI 2 //数据块类型
struct msgbuf {
long mtype;
char mtext[1024];
};
int main()
{
int msgid = -1;
msgid = msgget(IPC_KEY, IPC_CREAT | 0664);
if (msgid < 0) {
perror("msgget error");
return -1;
}
while (1) {
struct msgbuf buf;
//发送数据
memset(&buf, 0x00, sizeof(struct msgbuf));
buf.mtype = TYPE_CLI;
scanf("%s", buf.mtext);
msgsnd(msgid, &buf, 1024, 0);
//接收数据
msgrcv(msgid, &buf, 1024, TYPE_SER, 0);
printf("server say:[%s]\n", buf.mtext);
}
msgctl(msgid, IPC_RMID, NULL);
return 0;
}