C语言 消息队列

消息队列作为UNIX通信机制的一种,弥补了信号传递信息量有限的不足。它是一个消息链表,允许进程间按照特定规则发送和接收带有优先级的消息。系统V消息队列广泛应用,但为保持程序可移植性,推荐使用POSIX消息队列。消息队列在内核中持久存在,直到内核重启或显式删除。发送端和接收端通过消息队列进行通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

消息队列(也叫做报文队列)能够克服早期unix通信机制的一些缺点。作为早期unix通信机制之一的信号能够传送的信息量有限,后来虽然POSIX 1003.1b在信号的实时性方面作了拓广,使得信号在传递信息量方面有了相当程度的改进,但是信号这种通信方式更像"即时"的通信方式,它要求接受信号的进程在某个时间范围内对信号做出反应,因此该信号最多在接受信号进程的生命周期内才有意义,信号所传递的信息是接近于随进程持续的概念(process-persistent);管道及有名管道则是典型的随进程持续IPC,并且,只能传送无格式的字节流无疑会给应用程序开发带来不便,另外,它的缓冲区大小也受到限制。
消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息。消息队列是随内核持续的。
目前主要有两种类型的消息队列:POSIX消息队列以及系统V消息队列,系统V消息队列目前被大量使用。考虑到程序的可移植性,新开发的应用程序应尽量使用POSIX消息队列。
系统V消息队列是随内核持续的,只有在内核重起或者显式删除一个消息队列时,该消息队列才会真正被删除。因此系统中记录消息队列的数据结构(struct ipc_ids msg_ids)位于内核中,系统中的所有消息队列都可以在结构msg_ids中找到访问入口。 消息队列就是一个消息的链表。每个消息队列都有一个队列头,用结构struct msg_queue来描述。队列头中包含了该消息队列的大量信息,包括消息队列键值、用户ID、组ID、消息队列中消息数目等等,甚至记录了最近对消息队列读写进程的ID。读者可以访问这些信息,也可以设置其中的某些信息。


发送端

/*************************************************************************
	> File Name: msg_send.c
	> Author: kid
	> Mail: 280197326@qq.com 
	> Created Time: 2014年03月01日 星期六 23时15分47秒
 ************************************************************************/

#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<linux/msg.h>
#define MAXMSG 512
struct my_msg   //消息队列结构体
{
	long int my_msg_type;
	int i;
	char some_text[MAXMSG];
}msg;
main()
{
	int msgid;
	char buffer[BUFSIZ];
	msgid=msgget(12,0666|IPC_CREAT);  //创建消息队列

	while(1){
		puts("Enter some text:");
		fgets(buffer,BUFSIZ,stdin);
		msg.i++;
		printf("i=%d\n",msg.i);
		msg.my_msg_type=3;
		strcpy(msg.some_text,buffer);
		msgsnd(msgid,&msg,MAXMSG,0);   //发送数据到缓冲区
		if(strncmp(msg.some_text,"end",3)==0){   //比较输入,若为end则跳出循环
		    break;
        }
    }
	exit(0);
}

接收端

/*************************************************************************
	> File Name: msg_receive.c
	> Author: kid
	> Mail: 280197326@qq.com 
	> Created Time: 2014年03月01日 星期六 23时24分02秒
 ************************************************************************/

#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<linux/msg.h>

#define MAXMSG 512
struct my_msg
{
	long int my_msg_type;
	int i;
	char some_text[MAXMSG];
}msg;
main()
{
	int msgid;
	msg.my_msg_type=3;
	msgid=msgget(12,0666|IPC_CREAT);
	while(1)
	{
		msgrcv(msgid,&msg,BUFSIZ,msg.my_msg_type,0);
		printf("You wrote:%s and i=%d\n",msg.some_text,msg.i);
		if(strncmp(msg.some_text,"end",3)==0)
			break;
	}
	msgctl(msgid,IPC_RMID,0);
	exit(0);
}




在C语言中,消息队列是一种进程间通信(IPC)的机制,允许进程之间通过队列传递消息。消息队列可以在系统内核中维护,允许不同的进程发送和接收数据。以下是一个简单的示例,展示如何使用消息队列: ### 示例代码 ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ipc.h> #include <sys/msg.h> // 定义消息结构 struct msg_buffer { long msg_type; char msg_text[100]; } message; int main() { key_t key; int msgid; // 生成唯一的key key = ftok("progfile", 65); // 创建消息队列 msgid = msgget(key, 0666 | IPC_CREAT); message.msg_type = 1; printf("写入数据到消息队列: "); fgets(message.msg_text, 100, stdin); // 发送消息到消息队列 msgsnd(msgid, &message, sizeof(message), 0); printf("从消息队列读取的数据: "); msgrcv(msgid, &message, sizeof(message), 1, 0); printf("%s", message.msg_text); // 删除消息队列 msgctl(msgid, IPC_RMID, NULL); return 0; } ``` ### 代码说明 1. **消息结构定义**:`msg_buffer` 结构定义了消息类型和消息内容。 2. **生成Key**:`ftok` 函数用于生成一个唯一的key。 3. **创建消息队列**:`msgget` 函数用于创建或访问一个消息队列。 4. **发送消息**:`msgsnd` 函数用于发送消息到消息队列。 5. **接收消息**:`msgrcv` 函数用于从消息队列中接收消息。 6. **删除消息队列**:`msgctl` 函数用于删除消息队列。 ### 注意事项 - **权限设置**:在创建消息队列时,权限标志`0666`表示所有用户都有读写权限。 - **消息类型**:`msg_type` 必须是一个正整数,用于标识消息的类型。 - **错误处理**:在实际应用中,应检查每个系统调用的返回值,以确保操作成功。 ### 编译与运行 - 编译:使用`gcc`编译程序,例如: ```bash gcc msg_queue.c -o msg_queue ``` - 运行: ```bash ./msg_queue ``` 这个示例展示了如何在C语言中使用消息队列进行进程间通信。你可以根据需要扩展和修改此代码以适应具体的应用场景。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值