1.基础概念
消息队列,Unix的通信机制之一,可以理解为是一个存放消息(数据)容器。将消息写入消息队列,然后再从消息队列中取消息,一般来说是先进先出的顺序。
消息队列本质上是位于内核空间的链表,链表的每个节点都是一条消息。每一条消息都有自己的消息类型,消息类型用整数来表示,而且必须大于 0。每种类型的消息都被对应的链表所维护。
ftok:
消息队列具有一个唯一的键值,或称引用标识符、消息队列的ID号,通过使用ftok()函数获取,函数原型:
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(char *pathname, char proj);
获取成功返回消息队列的键值,失败返回-1。
参数pathname为一任意存在的路径名,参数proj为1~255之间的任一数字,ftok根据路径名,提取文件信息,再根据这些文件信息及proj的值合成key。(注:此段参考:ftok()函数深度解析)。
ftock()函数并不直接对消息队列操作,生成的键值用于msgget()函数使用,该函数用于创建或打开一个消息队列,其函数原型如下:
msgget:
运行成功则返回消息队列的引用标识符(ID),失败则返回-1。
参数key是ftok()
产生的键值,参数msgflg是一些标志位,可以取IPC_CREAT(没有消息队列就创建,有就打开)
、IPC_EXCL
、IPC_NOWAIT
或三者的逻辑或结果。
扫描二维码关注公众号,回复:
15954726 查看本文章
在以下两种情况下,msgget()
将创建一个新的消息队列:
- 如果没有消息队列与键值key相对应,且msgflg中包含了
IPC_CREAT
标志位 - key参数为
IPC_PRIVATE
msgsnd:
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */ 所要发送的信息
}; // 可以是其他类型,int double
//所以信息大小 sizeof(buff) - sizeof(buff.mtype)
msgrcv:
msgctl
2.父子进程消息队列
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/msg.h>
#define MY_TYPE 9527
int main(void)
{
int msgid; // 返回消息队列的描述符
pid_t pid;
// 定义消息内容
struct msgbuf
{
long mtype;
char mtext[100];
int number;
};
struct msgbuf buff;
msgid = msgget(IPC_PRIVATE, IPC_CREAT|0660); // 创建消息队列
pid = fork(); // 创建进程
if(pid > 0) // 父进程
{
sleep(5);
buff.mtype = MY_TYPE;
printf("please enter the string you want to send:\n");
gets(buff.mtext);
printf("please enter a number you want to send:\n");
scanf("%d", &buff.number); //
msgsnd(msgid, &buff, sizeof(buff) - sizeof(buff.mtype), 0);
//msgsnd 发送消息 1.返回消息队列的描述符 2.指针,指向自定义结构体 3.内容大小
waitpid(pid, NULL, 0); // 等待子进程结束
}
else if(pid == 0) // 子进程
{
printf("child process is waiting for message:\n"); // 消息类型
msgrcv(msgid, &buff, sizeof(buff) - sizeof(buff.mtype), MY_TYPE, 0);
// msgrcv 接收信息 buff 复制的父进程的用于存放收到的信息 接收信息类型与输入信息类型相同
printf("child process read from msg: %s, %d\n", buff.mtext, buff.number);
msgctl(msgid, IPC_RMID, NULL); // 删除
}
else
perror("fork");
return 0;
}
3.非亲属关系进程消息队列
send_msg.c
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/msg.h>
#define MY_TYPE 9527
#define MY_KEY 1314 //也可以使用ftok,避免冲突
// 定义消息内容
struct msgbuf
{
long mtype;
char mtext[100];
int number;
};
int main(void)
{
int msgid;
struct msgbuf buff;
msgid = msgget(MY_KEY, 0666|IPC_CREAT); // 创建消息队列
buff.mtype = MY_TYPE;
printf("please enter the string you want to send:\n");
gets(buff.mtext);
printf("please enter a number you want to send:\n");
scanf("%d", &buff.number);
msgsnd(msgid, &buff, sizeof(buff) - sizeof(buff.mtype), 0); //msgsnd发送消息 指针 内容大小
return 0;
}
recv_msg.c
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/msg.h>
#define MY_TYPE 9527
#define MY_KEY 1314
// 定义消息内容
struct msgbuf
{
long mtype;
char mtext[100];
int number;
};
int main(void)
{
int msgid;
struct msgbuf buff;
msgid = msgget(MY_KEY, 0666|IPC_CREAT); // 创建消息队列
while(1)
{
printf("process is waiting for msg:\n");
msgrcv(msgid, &buff, sizeof(buff) - sizeof(buff.mtype), MY_TYPE, 0)
prinrf("process read from msg: %s, %d\n", buff.mtext, buff.number);
}
msgctl(msgid, IPC_RMID, NULL);
return 0;
}