多进程编程(三):消息队列

本文详细介绍了消息队列的基本概念,包括其工作原理、创建与操作方法(如msgget, msgsnd, msgrcv),并通过实例演示了如何使用C语言实现消息的发送和接收。重点展示了消息队列如何解决传统管道的局限,并强调了其灵活性和类型化的优点。
摘要由CSDN通过智能技术生成
消息队列

**消息队列,就是一个消息的链表,是一系列保存在内核中消息的列表。**用户进程可以向消息队列添加消息,也可以向消息队列读取消息。
消息队列克服了管道只能承载无格式字节流以及缓冲区大小受限等缺点。
其优势是对每个消息指定特定的消息类型,接收的时候可以根据自定义条件接收特定类型的消息,而不一定像管道那样必须以先进先出的方式接收数据。

消息数据由结构体组成
struct msgbuf {
	long msg_type; // 信息类型
	char msg[size_t]; // 保存信息的数组
};
函数:

1、必备头文件

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

2、创建消息队列

int msgget(key_t key, int msgflg);
- key是一个键值,用来标识一个全局唯一的消息队列,一般使用十六进制数表示
- msgflg表示所需要的操作和权限,可以用来控制和创建一个消息队列
	IPC_CREAT
	IPC_EXCL
	IPC_CREAT | IPC_EXCL
- 返回值:
	调用成功:返回消息队列的标识号
	调用失败:返回 -1

3、向消息队列中写入消息

int msgsnd(int msgid, const void *ptr, size_t nbytes, int flag);
- msgid表示消息队列的标识号
- ptr表示消息结构体的指针(存放数据的结构体指针)
- nbytes表示消息结构体中字符数组的大小
- flag表示消息队列选择的模式
	0 -- 当消息队列满时,msgsnd会阻塞进程,直到消息能写进消息队列中或者消息队列被删除
	IPC_NOWAIT -- 不会阻塞进程,会立即返回 EAGAIN
- 返回值:
	调用成功:返回 0
	调用失败:返回 -1

4、从消息队列中读取信息

size_t msgrcv(int msgid, void *ptr, size_t nbytes, long type, int flag);
- msgid表示消息队列的标识号
- ptr表示消息结构体的指针(存放数据的结构体指针)
- nbytes表示消息结构体中字符数组的大小
- type表示根据类型读取消息队列中的数据
	0 -- 返回队列中的第一个消息
	>0 -- 返回队列中消息类型为 type 的第一个消息
	<0 -- 返回队列中消息类型值小于等于 type绝对值的消息,如果这种消息有好多个,则取类型最小的消息
- flag:
	0 -- 阻塞进程,直到成功读取到信息为止
	IPC_NOWAIT -- 如果读取不到信息立即返回,错误码为 ENOMSG
- 返回值:
	调用成功:返回消息数据的长度
	调用失败:返回 -1

5、删除消息队列

int msgctl(int msgid, int cmd, struct msqid_ds *buf);
- msgid表示消息队列的标识号
- cmd:
	IPC_RMID
- buf设置为 NULL
举例
// write_msg.c
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>

struct msgbuf {
        long int mymsg_type;
        char msg[100];
} msg;

int main() {
    // 创建消息队列
    int msgid = msgget((key_t)0x5005, IPC_CREAT | 0666);
    if (msgid == -1) {
        perror("msgget!");
    }
		
		// 提前准备数据,并拷贝至消息队列结构体中
    msg.mymsg_type = 1;
    char buf[100] = "Hello world!\n This is my show!";
    memcpy(msg.msg, buf, strlen(buf));
		
		// 将消息发送到消息队列中
    int res = msgsnd(msgid, &msg, 100, 0);
    if (res == -1) {
        perror("msgsnd!");
    }

    return 0;
}
// read_msg.c
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>

struct msgbuf {
        long int mymsg_type;
        char msg[100];
} msg;

int main() {
    // 创建消息队列
    int msgid = msgget((key_t)0x5005, IPC_CREAT | 0666);
    if (msgid == -1) {
        perror("msgget!");
    }
    
    // 读取消息队列中的数据
    int res = msgrcv(msgid, &msg, 100, 1, IPC_NOWAIT); // 非阻塞读取
    if (res == -1) {
        perror("msgsnd!");
    }
    
    // 打印数据
    printf("%s\n", msg.msg);

    return 0;
}
查看消息队列
ipcs -q # 查看现有消息队列

ipcrm -q msgid # 根据消息队列标识号,删除消息队列
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值