IPC消息队列问题:如何识别每条发送消息的消息类型?
IPC消息队列问题:接收端无法正确获取每条消息的类型
问题描述
刚学习IPC消息队列,编写了两个共用密钥的进程:一个发送消息,另一个读取消息后删除队列。现在遇到问题:需要识别每条发送消息对应的类型,期望每条消息的mtype与发送时一致,但接收端仅能打印最后一条消息的类型,无法获取每条消息的类型以进行排序。
控制台输出
MSG sent: MSG_6 MSG sent: MSG_2 MSG sent: MSG_8 MSG sent: MSG_9 MSG sent: MSG_8 MSG sent: MSG_3 MSG sent: MSG_6 MSG sent: MSG_6 MSG sent: MSG_2 MSG sent: MSG_5 Recieved type: 5, MSG_6 Recieved type: 5, MSG_2 Recieved type: 5, MSG_8 Recieved type: 5, MSG_9 Recieved type: 5, MSG_8 Recieved type: 5, MSG_3 Recieved type: 5, MSG_6 Recieved type: 5, MSG_6 Recieved type: 5, MSG_2 Recieved type: 5, MSG_5 Now removing the QEUE in 3 seconds
相关代码
IPC_COMMON.h
#include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <errno.h> #define TEST_ERROR if (errno) {fprintf(stderr, \ "%s:%d: PID=%5d: Error %d (%s)\n", \ __FILE__, \ __LINE__, \ getpid(), \ errno, \ strerror(errno));} #define MSG_LEN 120 struct msgbuf { long mtype; char mtext[MSG_LEN]; }; #define MY_KEY 0x123456 #define MSGTYPE_RM 7
SENDER.c
#include "testCommon.h" #include <time.h> int main() { int id_q; struct msgbuf my_msg; int typeArr[10]; int i; id_q = msgget(MY_KEY, IPC_CREAT | 0600); TEST_ERROR; srand(time(NULL)); for(i = 0; i < 10; i++) { typeArr[i] = rand() % 10; my_msg.mtype = typeArr[i]; printf("Printing types %d\n", typeArr[i]); } for(i = 0; i < 10; i++) { switch(typeArr[i]) { case 0: strcpy(my_msg.mtext , "MSG_0"); msgsnd(id_q, &my_msg, MSG_LEN, 0); printf("MSG sent: %s\n", my_msg.mtext); break; case 1: strcpy(my_msg.mtext , "MSG_1"); msgsnd(id_q, &my_msg, MSG_LEN, 0); printf("MSG sent: %s\n", my_msg.mtext); break; case 2: strcpy(my_msg.mtext , "MSG_2"); msgsnd(id_q, &my_msg, MSG_LEN, 0); printf("MSG sent: %s\n", my_msg.mtext); break; case 3: strcpy(my_msg.mtext , "MSG_3"); msgsnd(id_q, &my_msg, MSG_LEN, 0); printf("MSG sent: %s\n", my_msg.mtext); break; case 4: strcpy(my_msg.mtext , "MSG_4"); msgsnd(id_q, &my_msg, MSG_LEN, 0); printf("MSG sent: %s\n", my_msg.mtext); break; case 5: strcpy(my_msg.mtext , "MSG_5"); msgsnd(id_q, &my_msg, MSG_LEN, 0); printf("MSG sent: %s\n", my_msg.mtext); break; case 6: strcpy(my_msg.mtext , "MSG_6"); msgsnd(id_q, &my_msg, MSG_LEN, 0); printf("MSG sent: %s\n", my_msg.mtext); break; case 7: strcpy(my_msg.mtext , "MSG_7"); msgsnd(id_q, &my_msg, MSG_LEN, 0); printf("MSG sent: %s\n", my_msg.mtext); break; case 8: strcpy(my_msg.mtext , "MSG_8"); msgsnd(id_q, &my_msg, MSG_LEN, 0); printf("MSG sent: %s\n", my_msg.mtext); break; case 9: strcpy(my_msg.mtext , "MSG_9"); msgsnd(id_q, &my_msg, MSG_LEN, 0); printf("MSG sent: %s\n", my_msg.mtext); break; default: fprintf(stderr, "Error occurred\n."); TEST_ERROR; } } return 0; }
RECEIVER.c
#include "testCommon.h" int main() { int q_id, num_bytes, i; struct msgbuf my_msg; num_bytes = 0; q_id = msgget(MY_KEY, IPC_CREAT | 0600); TEST_ERROR; while (1) { /* now receiving the message */ for(i = 0; i < 10; i++) { num_bytes += msgrcv(q_id, &my_msg, MSG_LEN, 0, 0); printf("Recieved type: %ld, %s \n", my_msg.mtype, my_msg.mtext); } if(num_bytes >= 0) break; } printf("Now removing the QEUE in 3 seconds\n"); sleep(3); msgctl(q_id, IPC_RMID, NULL); }
问题原因与修复方案
问题根源
发送端逻辑错误:第一个循环给my_msg.mtype赋值了10次,但第二个循环发送消息时,没有重新设置对应索引的mtype。第一个循环结束后,my_msg.mtype最终保留的是最后一次赋值的typeArr[9]的值(即控制台输出里的5),后续所有发送的消息都使用这个固定的mtype,导致接收端读到的所有消息类型都是5。
修复代码(修改SENDER.c)
在第二个循环的每次发送前,重新设置my_msg.mtype为当前typeArr[i]:
for(i = 0; i < 10; i++) { // 新增:每次发送前设置对应消息类型 my_msg.mtype = typeArr[i]; switch(typeArr[i]) { case 0: strcpy(my_msg.mtext , "MSG_0"); msgsnd(id_q, &my_msg, MSG_LEN, 0); printf("MSG sent: %s\n", my_msg.mtext); break; // 其他case代码保持不变 } }
更简洁的优化方式是合并两个循环,避免维护额外的typeArr数组:
for(i = 0; i < 10; i++) { my_msg.mtype = rand() % 10; printf("Printing types %ld\n", my_msg.mtype); switch(my_msg.mtype) { case 0: strcpy(my_msg.mtext , "MSG_0"); break; case 1: strcpy(my_msg.mtext , "MSG_1"); break; case 2: strcpy(my_msg.mtext , "MSG_2"); break; case 3: strcpy(my_msg.mtext , "MSG_3"); break; case 4: strcpy(my_msg.mtext , "MSG_4"); break; case 5: strcpy(my_msg.mtext , "MSG_5"); break; case 6: strcpy(my_msg.mtext , "MSG_6"); break; case 7: strcpy(my_msg.mtext , "MSG_7"); break; case 8: strcpy(my_msg.mtext , "MSG_8"); break; case 9: strcpy(my_msg.mtext , "MSG_9"); break; default: fprintf(stderr, "Error occurred\n."); TEST_ERROR; } msgsnd(id_q, &my_msg, MSG_LEN, 0); printf("MSG sent: %s\n", my_msg.mtext); }
额外优化点
- 头文件引用错误:发送端代码里写的是
#include "testCommon.h",实际头文件名为IPC_COMMON.h,需要统一,否则编译会报错。 msgsnd的第三个参数建议使用strlen(my_msg.mtext)+1代替固定的MSG_LEN,避免发送多余的空字符,提升效率。
内容的提问来源于stack exchange,提问作者Bilguun Batsaikhan
相关产品推荐
相关产品推荐

