C IPC - 无法从队列接收消息

Posted

技术标签:

【中文标题】C IPC - 无法从队列接收消息【英文标题】:C IPC - cannot receive message from queue 【发布时间】:2018-01-06 22:58:58 【问题描述】:

我用 C 语言编写了一个使用 IPC 消息队列的简单程序,但是当我将消息作为指针发送时,我无法接收到消息。

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <error.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <ctype.h>
#include <string.h>

typedef struct Message 
    long type;
    char content[16];
 Message;

int main(int argc, char* argv[]) 

    printf("Starting...\n");
    key_t key = 1;
    Message* msg = malloc(sizeof(Message));
    int msg_id = msgget(key, IPC_CREAT | 0777);
    printf("ID of the created queue: %d\n", msg_id);
    strcpy(msg->content, "Hello");
    msgsnd(msg_id, msg, 16, 0);
    free(msg);

    if (fork() == 0) 
        int msgid = msgget(key, 0);
        printf("Message queue id: %d\n", msgid);
        Message rcvMsg;
        msgrcv(msgid, &rcvMsg, 16, 0, 0);
        printf("Received: %s\n", rcvMsg.content);

        if (msgctl(msgid, IPC_RMID, 0) != 0) 
            perror("Cannot remove queue from system.\n");
            exit(1);
        

        exit(0);
    

    wait(NULL);
    printf("Stop.\n");
    exit(0);

我得到的输出是:

Starting... ID of the created queue: 327680 Message queue id: 327680

程序正在等待。 但是,当我将消息作为标准变量(而不是指向结构的指针)发送时,消息就会被传递。

工作计划:

int main(int argc, char* argv[]) 

    printf("Starting...\n");
    key_t key = 1;
    Message msg;
    int msg_id = msgget(key, IPC_CREAT | 0777);
    printf("ID of the created queue: %d\n", msg_id);
    strcpy(msg.content, "Hello");
    msgsnd(msg_id, &msg, 16, 0);

    if (fork() == 0) 
        int msgid = msgget(key, 0);
        printf("Message queue id: %d\n", msgid);
        Message rcvMsg;
        msgrcv(msgid, &rcvMsg, 16, 0, 0);
        printf("Received: %s\n", rcvMsg.content);

        if (msgctl(msgid, IPC_RMID, 0) != 0) 
            perror("Cannot remove queue from system.\n");
            exit(1);
        

        exit(0);
    

    wait(NULL);
    printf("Stop.\n");
    exit(0);

这个程序返回预期的输出:

Starting... ID of the created queue: 327680 Message queue id: 327680 Received: Hello Stop.

发生了什么事?怎么了?怎么调试?

还有一个问题是创建结构变量的最佳方法是什么 - 指针还是非指针(顺便说一句。结构的非指针变量的名称是什么?)?

Message msg;Message* msg = malloc(sizeof(Message));

【问题讨论】:

"结构的非指针变量的名称是什么" --> "结构". “什么是创建结构变量的最佳方式 - 指针或非指针”应该是“什么是创建数据的最佳方式,作为 结构指向结构的指针?”。 编译所有警告和调试信息:gcc -Wall -Wextra -g。改进代码以获得没有警告。仔细阅读每个系统调用(参见intro(2))和标准函数(例如malloc(3)..)的文档。阅读ALP。 使用gdb debugger 或者valgrind 【参考方案1】:

您没有初始化消息的type 字段。 msgsnd 要求 type 字段为正整数值。

您应该更改代码,以便它检查每个具有返回值的函数的返回值。我通过将msgsnd(msg_id, msg, 16, 0); 更改为int result = msgsnd(msg_id, msg, 16, 0); 然后插入发现了这个错误:

if (result == -1)

    perror("msgsnd");
    exit(EXIT_FAILURE);

这告诉我msgsnd 的参数无效,所以我查看了它的文档,发现type 必须是肯定的。

您还应该检查msgrcv 的返回值。

对于像这样的小型结构,不需要malloc,除非您需要该结构在创建它的函数退出后继续存在。如果函数只是要使用消息结构并丢弃它,请在本地声明它。如果函数要返回一个消息结构给它的调用者,用malloc分配它并返回一个指针。 (然后调用者负责稍后通过将其指针传递给free 来释放它。)

【讨论】:

需要添加msg->type = 1;在msgsnd之前

以上是关于C IPC - 无法从队列接收消息的主要内容,如果未能解决你的问题,请参考以下文章

IPC之消息队列·即时通讯小程序

IPC - 消息队列(Message Queue)- 使用

IPC - 消息队列(Message Queue)- 使用

IPC - 消息队列(Message Queue)- 使用

IPC - 消息队列(Message Queue)- 使用

从消息队列接收