You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
}

额外优化点

  1. 头文件引用错误:发送端代码里写的是#include "testCommon.h",实际头文件名为IPC_COMMON.h,需要统一,否则编译会报错。
  2. msgsnd的第三个参数建议使用strlen(my_msg.mtext)+1代替固定的MSG_LEN,避免发送多余的空字符,提升效率。

内容的提问来源于stack exchange,提问作者Bilguun Batsaikhan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 23:06:11