设计两个独立进程,一个是发送进程,一个是接收进程,通过消息队列进行进程通信,以“end”作为结束消息。
ftok函数
系统建立IPC通讯(如使用消息队列进行进程中的通信)必须指定一个ID值 。
通常情况下,该ID值通过ftok函数得到 。
ftok函数作用:将已存在的路径名和一个整数标识符转换成为一个key_t值,称为IPC键
#include<sys/ipc.h>
key_t ftok( char * fname, int id )
// name是指定的文档名,或者一个路径名
// id是子序号。 1-255
// key_t 返回类型,通常是至少32位的整数
// 返回值:当成功执行的时候,一个key_t值将会被返回,否则返回-1。
在一般的UNIX实现中,是将文档的索引节点号取出,前面加上子序号得到key_t的返回值。如指定文档的索引节点号为65538,
换算成16进制为0x010002,而指定的ID值为38,换算成16进制 为 0x26,则最后的key_t返回值为0x26010002。
msgget函数
msgget函数作用:得到消息队列标识符或创建一个消息队列对象并返回消息队列标识符
#include <sys/msg.h>
int msgget(key_t key, int msgflg)
// 通常情况下msgflg=IPC_CREAT:
// 如果内核中不存在键值与key相等的消息队列,则新建一个消息队列;
// 如果存在这样的消息队列,返回此消息队列的标识符
mssget(key,0666|IPC_CREAT)
//而 0666 表示消息队列的权限设置为:
// 所有者具有读写权限 (0 对应没有权限,1 对应执行权限,2 对应写权限,
// 4 对应读权限,因此 6 表示 4 + 2 = 6);
// 组用户具有读写权限;
// 其他用户具有读写权限。
在函数调用 msgget 中的参数 0666 是一个用于设置消息队列权限的参数。
消息队列的权限
在 Linux 中,对于消息队列的权限,通常使用三位八进制数来表示。
具体来说:
第一位表示用户权限;
第二位表示组权限;
第三位表示其他用户权限。
这意味着所有用户都可以读取和写入该消息队列。在实际使用中,应根据具体情况设置适当的权限,以确保安全性。
权限表
msgrcv,msgsnd函数
作用:从消息队列中接收/发送消息
函数原型
#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);
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
//具体应用
struct message {
long msg_type; //消息的类型
char msg_text[100]; //消息的内容
};
struct message data;
msgrcv(msgid,&data,sizeof(data),1,0);
msgsnd(msgid, &data, sizeof(data), 0);
msgid:消息队列标识符(由msgget生成)
msgp:指向用户自定义的缓冲区的指针,用于存储信息
msgsz:缓冲区的大小
msgtyp:用于选择接收的消息类型。
msgtype == 0 返回队列中第一个消息
msgtype > 0 返回队列中消息类型为 msgtype 的第一个消息
msgtype < 0 返回队列中消息类型值 <= msgtype绝对值的信息,优先取值最小的
msgflg:控制函数行为的标志
msgflg=IPC_NOWAIT,队列没有可读消息不等待,返回ENOMSG错误
msgflg=MSG_NOERROR,
如果接收到的消息长度大于所提供缓冲区的大小 msgsz,则截断消息而不引发错误。
如果未设置此标志并且接收到的消息长度大于 msgsz,则会导致 msgrcv 函数返回错误
msgflg=0,在没有符合条件的消息时阻塞等待消息的到达
消息接受模块
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MAX_SIZE 100
struct message {
long msg_type; //消息的类型
char msg_text[MAX_SIZE]; //消息的内容
};
int main() {
key_t key;
int msgid;
struct message data;
key = ftok("./share", 65); //生成key
msgid = msgget(key, 066_6 | IPC_CREAT); //创建消息队列
// 从队列中获取消息直到收到结束消息
while (1) {
msgrcv(msgid, &data, sizeof(data), 1, 0);
printf("Data Received is : %s", data.msg_text);
// 收到结束消息
if (strcmp(data.msg_text, "end") == 0) {
break;
}
}
// 删除消息队列
msgctl(msgid, IPC_RMID, NULL);
return 0;
}
消息发送模块
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MAX_SIZE 100
struct message {
long msg_type; //消息的类型
char msg_text[MAX_SIZE]; //消息的内容
};
int main() {
key_t key;
int msgid;
struct message data;
key = ftok("./share", 65); //生成key
msgid = msgget(key, 0666 | IPC_CREAT); //创建消息队列
printf("Enter some text: ");
fgets(data.msg_text, MAX_SIZE, stdin);
data.msg_type = 1;
// 发送数据
while (strcmp(data.msg_text, "end\n") != 0) {
msgsnd(msgid, &data, sizeof(data), 0);
printf("Enter some text: ");
fgets(data.msg_text, MAX_SIZE, stdin);
}
// 发送结束消息
strcpy(data.msg_text, "end");
msgsnd(msgid, &data, sizeof(data), 0);
return 0;
}
参考资料
进程间通信方式——消息队列_#define msgmax 8192-CSDN博客
消息队列 - msgrcv - 《Linux API速查手册》 - 书栈网 · BookStack