Linux 消息队列
在Linux中,线程间消息队列可以通过使用System V消息队列或POSIX消息队列来实现。
- 使用System V消息队列: System V消息队列是一种基于IPC(Inter-process Communication,进程间通信)的通信机制,可以用于进程或线程间的通信。下面是使用System V消息队列实现线程间通信的步骤:
a. 创建消息队列: 可以使用msgget()
函数来创建一个新的消息队列。例如:
key_t key = ftok("path_to_key_file", 'A');
int msgid = msgget(key, IPC_CREAT | 0666);
b. 发送消息: 使用msgsnd()
函数向消息队列发送消息。例如:
struct message {
long mtype;
char mtext[256];
};
struct message msg;
msg.mtype = 1;
strcpy(msg.mtext, "Hello, world!");
msgsnd(msgid, &msg, sizeof(msg.mtext), 0);
c. 接收消息: 使用msgrcv()
函数从消息队列接收消息。例如:
struct message msg;
msgrcv(msgid, &msg, sizeof(msg.mtext), 1, 0);
printf("Received message: %s\n", msg.mtext);
- 使用POSIX消息队列: POSIX消息队列是Linux中提供的另一种消息队列实现方式,它提供了更多的功能和灵活性。下面是使用POSIX消息队列实现线程间通信的步骤:
a. 创建消息队列: 可以使用mq_open()
函数创建一个新的消息队列。例如:
mqd_t mq = mq_open("/my_queue", O_CREAT | O_RDWR, 0666, NULL);
b. 发送消息: 使用mq_send()
函数向消息队列发送消息。例如:
char msg[] = "Hello, world!";
mq_send(mq, msg, sizeof(msg), 0);
c. 接收消息: 使用mq_receive()
函数从消息队列接收消息。例如:
char buf[256];
mq_receive(mq, buf, sizeof(buf), NULL);
printf("Received message: %s\n", buf);
需要注意的是,POSIX消息队列的名称在文件系统中是可见的,可以使用路径名来创建和打开消息队列。
整体实现:
发送到队列中去
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define MSGSZ 512
struct msg_buffer
{
long mtype;
char mtext[MSGSZ];
int age;
double many;
}msg_buf;
int main(){
key_t ftok_key=ftok("./msg1", 'b');
//创建消息队列
int msgget_id=msgget(ftok_key, IPC_CREAT|0666);
//写入队列
msg_buf.mtype=1;
msg_buf.age=168;
msg_buf.many=123.456;
strcpy(msg_buf.mtext, "“我今天去超市,结果发现超市里没有超市");
//key 指针类型的结构体 消息正文大小 发送标志
int msgend_stat=msgsnd(msgget_id, &msg_buf, sizeof(msg_buf)-sizeof(msg_buf.mtype), 0);
msg_buf.mtype=8;
strcpy(msg_buf.mtext, "我昨天梦见自己醒来了,结果今天真的醒来了");
//key 指针类型的结构体 消息正文大小 发送标志
int msgend_stat1=msgsnd(msgget_id, &msg_buf, sizeof(msg_buf.mtext), 0);
msg_buf.mtype=5;
strcpy(msg_buf.mtext, "我试图在网上搜索‘如何上网’,结果电脑告诉我‘无法连接到互联网’");
//key 指针类型的结构体 消息正文大小 发送标志
int msgend_stat2=msgsnd(msgget_id, &msg_buf, sizeof(msg_buf.mtext), 0);
return 0;
}
接收
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <stdlib.h>
#define MSGSZ 512
struct msg_buffer
{
long mtype;
char mtext[MSGSZ];
int age;
double many;
}msg_buf;
int main() {
// 创建唯一的key
key_t ftok_key = ftok("./msg1", 'b');
// 访问消息队列
int msgid = msgget(ftok_key, 0666 | IPC_CREAT);
if (msgid == -1) {
perror("msgget error");
exit(1);
}
// 接收消息
//key 接收的大小 读取类型为msgtyp的第一条消息 0: 阻塞接收,直到有消息到达
if (msgrcv(msgid, &msg_buf, sizeof(msg_buf.mtext), 8, 0) == -1) {
perror("msgrcv error");
exit(1);
}
printf("msg_buf received by child process: %s\n", msg_buf.mtext);
sleep(1);
if (msgrcv(msgid, &msg_buf, sizeof(msg_buf)-sizeof(msg_buf.mtype), 1, 0) == -1) {
perror("msgrcv error");
exit(1);
}
printf("msg_buf received by child process: %s 岁是%d 钱是:%.3fd\n", msg_buf.mtext, msg_buf.age, msg_buf.many);
sleep(1);
if (msgrcv(msgid, &msg_buf, sizeof(msg_buf.mtext), 5, 0) == -1) {
perror("msgrcv error");
exit(1);
}
printf("msg_buf received by child process: %s\n", msg_buf.mtext);
sleep(1);
// 删除消息队列
if (msgctl(msgid, IPC_RMID, NULL) == -1) {
perror("msgctl error");
exit(1);
}
return 0;
}