Linux进程通信之消息队列
目录
2.函数msgrcv在读取消息队列时,type参数有下面几种情况:
3.函数msgctl对消息队列进行操作时cmd常用的操作命令有
1、消息队列介绍
消息队列(Message Queue)是一种在进程间进行通信的机制,是消息的链接表,允许一个进程向另一个进程发送数据。消息队列是通过在内核中创建的一个消息缓冲区来实现的,允许多个进程向同一队列发送消息,并从中读取消息。
2、消息队列的特点
- 消息队列中的消息通常是一个结构体,包含一个消息类型标识符和实际的消息数据。接收进程可以选择接收特定类型的消息。
- 每个消息队列都有一个唯一的标识符,用于标识消息队列。进程通过这个标识符访问消息队列。
- 消息队列是独立于发送和接收进程,进程终止时消息队列机器内容并不会被删除,由Linux内核来决定消息队列及其内容什么时候被删除。
- 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
?3、消息队列涉及的函数
?// 创建或打开消息队列:成功返回队列ID,失败返回-1
1 int msgget(key_t key, int msgflg);
?// 写入消息:成功返回0,失败返回-1
2 int msgsnd(int msqid, const void *ptr, size_t size, int msgflg);
?// 读取消息:成功返回接收到的消息的字节数,失败返回-1
3 int msgrcv(int msqid, void *ptr, size_t size, long type,int msgflg);
?// 控制消息队列:成功返回0,失败返回-1
?4 int msgctl(int msqid, int cmd, struct msqid_ds *buf);
1.msgflg参数的两个主要标志位:
- IPC_CREAT: 如果消息队列不存在,则创建一个新的消息队列。
- IPC_EXCL: 与
IPC_CREAT
一同使用时,如果消息队列已经存在,则返回错误。如果未指定IPC_EXCL
,即使消息队列已经存在,也会返回其标识符。?
当创建一个新的消息队列时,我们需要在标志位IPC_CREAT的后面或(|)上消息队列的访问权限,表示当key命名的消息队列不存在时创建一个消息队列,当key所命名的消息队列存在时则被忽略。
2.函数msgrcv在读取消息队列时,type参数有下面几种情况:
- type == 0,返回队列中的第一个消息;
- type > 0,返回队列中消息类型为 type 的第一个消息;
- type < 0,返回队列中消息类型值小于或等于 type 绝对值的消息,如果有多个,则取类型值最小的消息。
可以看出,type值非 0 时用于以非先进先出次序读消息。也可以把 type 看做优先级的权值
3.函数msgctl对消息队列进行操作时cmd
常用的操作命令有
- IPC_STAT: 获取消息队列的状态信息,将其存储在
buf
中。 - IPC_SET: 设置消息队列的状态信息,使用
buf
中提供的值。 - IPC_RMID: 删除消息队列。
而参数buf
:指向 struct msqid_ds
结构体的指针,用于传递或接收消息队列的状态信息,当我们使用的是IPC_RMID时这里可以设置为空。
4、ftok函数的单独介绍
ftok
函数用于生成一个与文件路径名和项目 ID 相关的键值函数原型:key_t ftok(const char *pathname, int proj_id);
参数介绍:
pathname
:文件路径名,可以是一个现有的文件。通常选择一个存在的文件,因为ftok
使用文件的 inode 号和 proj_id 来生成键值。proj_id
:项目 ID,为整数。
ftok
函数通过将文件的 inode 号和项目 ID 整合在一起,产生一个唯一的键值。这个键值在 IPC 对象(例如消息队列、信号量、共享内存)的创建和访问中用于标识对象。
5、示例
发送并接收
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
// 定义消息结构体
struct msgbuf {
long mtype; // 消息类型,必须大于 0
char mtext[128]; // 消息数据
int index; // 额外的索引信息
};
int main() {
// 通过 ftok 创建键值
key_t key = ftok(".", 5);
printf("key = %x\n", key);
// 创建或获取消息队列
int msqid = msgget(key, 0777 | IPC_CREAT);
if (msqid == -1) {
printf("msgget 失败!!!\n");
perror("why");
} else {
// 发送消息
struct msgbuf sendbuf = {88, "happy bay!!!", 88};
msgsnd(msqid, &sendbuf, strlen(sendbuf.mtext) + sizeof(sendbuf.index), 0);
// 接收消息
struct msgbuf rcvbuf;
msgrcv(msqid, &rcvbuf, sizeof(rcvbuf.mtext) + sizeof(rcvbuf.index), 100, 0);
printf("read: %s, index: %d\n", rcvbuf.mtext, rcvbuf.index);
}
// 删除消息队列
msgctl(key, IPC_RMID, NULL);
return 0;
}
接收并发送
#include <sys/types.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
// 定义消息结构体
struct msgbuf {
long mtype; // 消息类型,必须大于 0
char mtext[128]; // 消息数据
int index; // 额外的索引信息
};
int main() {
// 通过 ftok 创建键值
key_t key = ftok(".", 5);
printf("key = %x\n", key);
// 创建或获取消息队列
int msqid = msgget(key, 0777 | IPC_CREAT);
if (msqid == -1) {
printf("msgget 失败!!!\n");
perror("why");
} else {
// 接收消息
struct msgbuf rcvbuf;
msgrcv(msqid, &rcvbuf, sizeof(rcvbuf.mtext) + sizeof(rcvbuf.index), 88, 0);
printf("read: %s, index = %d\n", rcvbuf.mtext, rcvbuf.index);
// 发送消息
struct msgbuf sendbuf = {100, "thank you wjh !!!", 100};
msgsnd(msqid, &sendbuf, strlen(sendbuf.mtext) + sizeof(sendbuf.index), 0);
}
// 删除消息队列
msgctl(key, IPC_RMID, NULL);
return 0;
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!