C 程序中 fork() 和消息队列通信的问题

问题描述 投票:0回答:1

在我的程序中,当进程从消息队列接收到消息“ON”时,我尝试分叉一个进程。在引入分叉之前,消息可以正常工作:

    while (1)
    {
        receive_message(msg_queue_id, data, sizeof(data), getpid());
        if (strcmp(data, "ON") == 0)
        {
            puts("Received");
        }
    }

但是,添加分叉后,程序表现出不一致的行为。最初的 10 个进程似乎受到了影响,值得注意的是,fork 并不总是失败;有成功的例子。

    while (1)
    {
        receive_message(msg_queue_id, data, sizeof(data), getpid());
        if (strcmp(data, "ON") == 0)
        {
            pid = fork();
            CATCH_ERROR;
            if (pid == 0)
            {
                puts("Received");
            }
        }
    }

fork失败时遇到的错误信息如下:

[错误] src/proc.c 行:32 PID = 22755 错误 42(没有所需类型的消息)

我很难理解为什么间歇性地分叉进程会导致消息队列出现问题。任何有关潜在原因以及如何解决这些问题的见解或建议将不胜感激。

我的期望是分叉进程不会干扰消息队列操作,但间歇性的“没有所需类型的消息”错误表明情况并非如此。我正在寻找潜在原因或替代方法来解决此问题。

    void receive_message(int msg_id, void *msg_ptr, size_t msg_size, int msg_type)
{
    struct msqid_ds buf;
    struct msgbuf message;
    message.mtype = msg_type;

    if (msgctl(msg_id, IPC_STAT, &buf) == -1)
    {
        if (errno != ENOMSG)
            CATCH_ERROR;

        return;
    }

    if (buf.msg_qnum == 0)
        return;

    if (msgrcv(msg_id, &message, msg_size, msg_type, IPC_NOWAIT) == -1)
    {
        if (errno != ENOMSG)
            CATCH_ERROR;

        return;
    }

    memcpy(msg_ptr, message.mtext, msg_size);
}
c linux fork ipc message-queue
1个回答
0
投票

假设一个进程从消息队列中读取“ON”。它写入“已接收”,然后尝试读取另一条消息。

msgrcv
返回-1并将
errno
设置为ENOMSG,因此
receive_message
返回时不会向
msg_ptr
写入任何数据,并且
data
仍然包含上次读取的“ON”。
strcmp
再次返回 0,
fork
被调用,父级和子级立即调用
CATCH_ERROR
宏,该宏(大概)根据当前
errno
中的内容写入错误消息。如果
strcmp
fork
都没有修改
errno
,那么该值仍然是
ENOMSG
,并且您会看到令人讨厌的错误消息。

© www.soinside.com 2019 - 2024. All rights reserved.