亲子沟通问题

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

父母有“m”条消息要发送给“n”个孩子。在每次迭代中,它向所有子节点发送一条消息。如果所有回复“已收到”,它会发送下一条消息。下面是我的代码

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

#define MAX_LEN 50

struct details
{
    int no;
    int id;
    char msg_text[MAX_LEN];
};

typedef struct msg_buf
{
    long int msg_type;
    struct details d;
} msg;

char message[20][50] =
{
    " ",
    "Message1",
    "Message2",
    "Message3",
    "Message4",
    "Message5",
    "Message6",
    "Message7",
    "Message8"
};

int main(int argc, char *argv[])
{
    int id1, id2, n, m, i, j, status, p_id;
    pid_t pid;
    msg snd, rcvd;

    if (argc < 2)
    {
        perror("Too few arguments");
        return -1;
    }
    n = atoi(argv[1]);
    m = atoi(argv[2]);

    id1 = msgget((key_t)78, IPC_CREAT | 0666);
    id2 = msgget((key_t)56, IPC_CREAT | 0666);

    if (id1 == -1 || id2 == -1)
    {
        printf("Error in creating message queue\n");
        return -1;
    }
    p_id = getpid();

    printf("\nQueues are created.\n\n");
    for (i = 1; i <= n; i++)
    {
        pid = fork();
        if (pid == 0)
            break;
    }

    if (pid == 0)
    {
        for (j = 1; j <= m; j++)
        {
            printf("Process %d waiting for message %d\n", getpid(), j);
            while (msgrcv(id1, &rcvd, sizeof(struct details), j + 1, IPC_NOWAIT) < 0)
            {
            }

            srand(time(0));
            strcpy(snd.d.msg_text, "Received");
            snd.msg_type = rcvd.msg_type;
            snd.d.no = rcvd.d.no;
            snd.d.id = getpid();

            if (msgsnd(id2, &snd, sizeof(struct details), IPC_NOWAIT) < 0)
            {
                perror("msgsnd");
            }
            else
            {
                printf("Reply sending successful for message %d for process %d\n", snd.d.no, snd.d.id);
            }
        }
    }

    if (p_id == getpid())
    {
        for (j = 1; j <= m; j++)
        {
            strcpy(snd.d.msg_text, message[j]);
            snd.msg_type = j + 1;
            snd.d.no = j;

            if (msgsnd(id1, &snd, sizeof(struct details), 0) < 0)
            {
                perror("msgsnd");
            }
            else
            {
                printf("Message %d sent- \t\t\t\t%s\n", j, snd.d.msg_text);
            }

            for (i = 1; i <= n; i++)
            {
                sleep(i);
                if (msgrcv(id2, &rcvd, sizeof(struct details), j + 1, 0) >= 0)
                {
                    printf("Reply received from child %d for message %d - \t%s\n", rcvd.d.id, j, rcvd.d.msg_text);
                }
            }
        }
        wait(NULL);
        printf("Communication End.\n\n");
    }
}

我得到的输出是n=2,m=2是:

Queues are created.

Message 1 sent- Message1
Process 14804 waiting for message 1
Process 14805 waiting for message 1
Reply sending successful for message 1 for process 14804
Process 14804 waiting for message 2
Reply received from child 14804 for message 1 - Received

此后什么也没有打印。没有任何进展。问题是什么?如何解决这个问题?

c ipc message-queue
1个回答
0
投票

最大的单一问题是在评论中提到的一个

AFAICS,您每次迭代发送一条消息,因此最多一个孩子可以阅读它。您不会向每个孩子发送一条消息。

任何给定的消息都可以被(最多)一个进程接收。对于

n
进程接收消息,您必须发送
n
消息。

其他问题主要是装饰性的。我使用了 GitHub 上我的 SOQ(堆栈溢出问题)存储库中可用的日志记录代码作为文件

stderr.c
stderr.h
src/libsoq 子目录中。一些消息被写入
stdout
— 没有只接受文件流的函数,所以我使用
err_logmsg()
接受文件流、控制选项和退出状态(但函数不应该退出,所以这是未使用的)以及格式和参数。

结果是:

/* SO 7592-2454 */
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <unistd.h>

#include "stderr.h"

#define MAX_LEN 50

struct details
{
    int no;
    int id;
    char msg_text[MAX_LEN];
};

typedef struct msg_buf
{
    long int msg_type;
    struct details d;
} msg;

static char message[20][50] =
{
    " ",
    "Message1",
    "Message2",
    "Message3",
    "Message4",
    "Message5",
    "Message6",
    "Message7",
    "Message8"
};

static const char usestr[] = "num_kids num_msgs";

static void dump_message(const char *tag, const msg *info)
{
    err_logmsg(stdout, err_getlogopts(), 0, "%s: type %ld (details: no %d, id %d, text [%s])\n",
               tag, info->msg_type, info->d.no, info->d.id, info->d.msg_text);
}

int main(int argc, char *argv[])
{
    err_setarg0(argv[0]);

    if (argc != 3)
        err_usage(usestr);
    int n = atoi(argv[1]);
    int m = atoi(argv[2]);

    int id1 = msgget((key_t)78, IPC_CREAT | 0666);
    int id2 = msgget((key_t)56, IPC_CREAT | 0666);

    if (id1 == -1 || id2 == -1)
        err_syserr("failed to create a message queue: ");

    pid_t p_id = getpid();

    err_setlogopts(ERR_PID|ERR_MILLI);
    err_logmsg(stdout, err_getlogopts(), 0, "Queues are created.\n");

    pid_t pid;
    for (int i = 1; i <= n; i++)
    {
        pid = fork();
        if (pid == 0)
            break;
    }

    msg snd;
    msg rcvd;

    if (pid == 0)
    {
        for (int j = 1; j <= m; j++)
        {
            err_logmsg(stdout, err_getlogopts(), 0, "Waiting for message %d\n", j);
            while (msgrcv(id1, &rcvd, sizeof(struct details), j + 1, IPC_NOWAIT) < 0)
                err_syserr("msgrcv() returned with error status: ");

            dump_message("Message received", &rcvd);

            strcpy(snd.d.msg_text, "Received");
            snd.msg_type = rcvd.msg_type;
            snd.d.no = rcvd.d.no;
            snd.d.id = getpid();

            if (msgsnd(id2, &snd, sizeof(struct details), IPC_NOWAIT) < 0)
                err_sysrem("msgsnd() failed: ");
            else
                dump_message("Message sent", &snd);
        }
        err_logmsg(stdout, err_getlogopts(), 0, "Child process complete\n");
        exit(EXIT_SUCCESS);
    }

    if (p_id == getpid())
    {
        for (int j = 1; j <= m; j++)
        {
            strcpy(snd.d.msg_text, message[j]);
            snd.msg_type = j + 1;
            snd.d.no = j;

            for (int i = 0; i < n; i++)
            {
                if (msgsnd(id1, &snd, sizeof(struct details), 0) < 0)
                    err_sysrem("msgsnd() failed: ");
                else
                    dump_message("Message sent", &snd);
            }

            for (int i = 1; i <= n; i++)
            {
                err_logmsg(stdout, err_getlogopts(), 0, "Dozing for %d seconds\n", i);
                sleep(i);
                if (msgrcv(id2, &rcvd, sizeof(struct details), j + 1, 0) >= 0)
                    dump_message("Reply received", &rcvd);
                else
                    err_syserr("msgrcv() failed: ");
            }
        }

        int corpse;
        int status;
        while ((corpse = wait(&status)) > 0)
            err_remark("Child %d exited with status 0x%.4X\n", corpse, status);
        err_logmsg(stdout, err_getlogopts(), 0, "Communication End.\n\n");
    }

    return 0;
}

有大量的日志记录,因为我需要看看发生了什么。代码应该验证

n
m
的值(它们应该至少是
1
并且不超过一些微弱的理智数字(例如
10
,但会有一个或两个值(枚举或定义常数)来限制可接受的范围。

这是一个示例输出(源代码

msg79.c
,程序
msg79
):

$ ./msg79 2 3
msg79: 2023-04-03 21:36:38.215 - pid=67247: Queues are created.
msg79: 2023-04-03 21:36:38.217 - pid=67247: Message sent: type 2 (details: no 1, id 1, text [Message1])
msg79: 2023-04-03 21:36:38.217 - pid=67247: Message sent: type 2 (details: no 1, id 1, text [Message1])
msg79: 2023-04-03 21:36:38.217 - pid=67247: Dozing for 1 seconds
msg79: 2023-04-03 21:36:38.217 - pid=67248: Waiting for message 1
msg79: 2023-04-03 21:36:38.217 - pid=67249: Waiting for message 1
msg79: 2023-04-03 21:36:38.217 - pid=67248: Message received: type 2 (details: no 1, id 1, text [Message1])
msg79: 2023-04-03 21:36:38.217 - pid=67249: Message received: type 2 (details: no 1, id 1, text [Message1])
msg79: 2023-04-03 21:36:38.217 - pid=67248: Message sent: type 2 (details: no 1, id 67248, text [Received])
msg79: 2023-04-03 21:36:38.217 - pid=67248: Waiting for message 2
msg79: 2023-04-03 21:36:38.217 - pid=67249: Message sent: type 2 (details: no 1, id 67249, text [Received])
msg79: 2023-04-03 21:36:38.218 - pid=67248: Message received: type 3 (details: no 2, id 1, text [Message2])
msg79: 2023-04-03 21:36:38.218 - pid=67249: Waiting for message 2
msg79: 2023-04-03 21:36:38.218 - pid=67249: Message received: type 3 (details: no 2, id 1, text [Message2])
msg79: 2023-04-03 21:36:38.218 - pid=67248: Message sent: type 3 (details: no 2, id 67248, text [Received])
msg79: 2023-04-03 21:36:38.218 - pid=67249: Message sent: type 3 (details: no 2, id 67249, text [Received])
msg79: 2023-04-03 21:36:38.218 - pid=67248: Waiting for message 3
msg79: 2023-04-03 21:36:38.219 - pid=67249: Waiting for message 3
msg79: 2023-04-03 21:36:38.219 - pid=67248: Message received: type 4 (details: no 3, id 1, text [Message3])
msg79: 2023-04-03 21:36:38.219 - pid=67249: Message received: type 4 (details: no 3, id 1, text [Message3])
msg79: 2023-04-03 21:36:38.219 - pid=67248: Message sent: type 4 (details: no 3, id 67248, text [Received])
msg79: 2023-04-03 21:36:38.219 - pid=67249: Message sent: type 4 (details: no 3, id 67249, text [Received])
msg79: 2023-04-03 21:36:38.219 - pid=67248: Child process complete
msg79: 2023-04-03 21:36:38.219 - pid=67249: Child process complete
msg79: 2023-04-03 21:36:39.219 - pid=67247: Reply received: type 2 (details: no 1, id 67248, text [Received])
msg79: 2023-04-03 21:36:39.219 - pid=67247: Dozing for 2 seconds
msg79: 2023-04-03 21:36:41.220 - pid=67247: Reply received: type 2 (details: no 1, id 67249, text [Received])
msg79: 2023-04-03 21:36:41.220 - pid=67247: Message sent: type 3 (details: no 2, id 1, text [Message2])
msg79: 2023-04-03 21:36:41.220 - pid=67247: Message sent: type 3 (details: no 2, id 1, text [Message2])
msg79: 2023-04-03 21:36:41.220 - pid=67247: Dozing for 1 seconds
msg79: 2023-04-03 21:36:42.221 - pid=67247: Reply received: type 3 (details: no 2, id 67248, text [Received])
msg79: 2023-04-03 21:36:42.221 - pid=67247: Dozing for 2 seconds
msg79: 2023-04-03 21:36:44.223 - pid=67247: Reply received: type 3 (details: no 2, id 67249, text [Received])
msg79: 2023-04-03 21:36:44.223 - pid=67247: Message sent: type 4 (details: no 3, id 1, text [Message3])
msg79: 2023-04-03 21:36:44.223 - pid=67247: Message sent: type 4 (details: no 3, id 1, text [Message3])
msg79: 2023-04-03 21:36:44.223 - pid=67247: Dozing for 1 seconds
msg79: 2023-04-03 21:36:45.227 - pid=67247: Reply received: type 4 (details: no 3, id 67248, text [Received])
msg79: 2023-04-03 21:36:45.227 - pid=67247: Dozing for 2 seconds
msg79: 2023-04-03 21:36:47.227 - pid=67247: Reply received: type 4 (details: no 3, id 67249, text [Received])
msg79: 2023-04-03 21:36:47.227 - pid=67247: Child 67249 exited with status 0x0000
msg79: 2023-04-03 21:36:47.227 - pid=67247: Child 67248 exited with status 0x0000
msg79: 2023-04-03 21:36:47.228 - pid=67247: Communication End.
$
© www.soinside.com 2019 - 2024. All rights reserved.