【问题标题】:How to communicate processes of a tree without external mechanisms如何在没有外部机制的情况下通信树的进程
【发布时间】:2016-12-20 14:09:44
【问题描述】:

我需要使用 fork() 在 C 中构建一个具有以下形状的进程树:

我必须在它们之间发送信号,所以我还想知道是否有任何方法可以将进程的 PID 存储在数组或其他东西中,所以每个进程都有其他进程的 PID。问题是我有一些限制,比如不使用管道、文件或其他外部机制在进程之间共享数据。 sleep 和 exec 都不能用。

这就是我必须在它们之间发送信号的方式:

【问题讨论】:

  • 共享内存不够?
  • 您只需按正确的顺序执行fork()s,偶尔调用getpid()getppid()
  • ... 特别是,每个进程没有必要拥有 all 其他进程的 PID。每个人只需要它需要发出信号的那些的PID。该练习似乎旨在按照@EOF 建议的方式提供解决方案。
  • 所以我只需要按照一定的顺序创建它们,所以在创建它们的那一刻,它们将发送信号的进程的 PID 已经创建了吗?谢谢!

标签: c process tree


【解决方案1】:

所以我只需要按照一定的顺序创建它们,所以在创建它们的那一刻,它们将发送信号的进程的 PID 已经创建了吗?

是的 - 特别是 H4 必须在 H3/N3 之前分叉,以便 N3 知道 H4。演示:

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

void handler(int signum, siginfo_t *si, void *u)
{
    printf("%d received signal from %d %s\n", getpid(), si->si_pid,
                                                        si->si_value.sival_ptr);
}

main()
{
    // for demo, defer signal delivery until process unmasks the signal
    sigset_t set, oldset;
    sigemptyset(&set);
    sigaddset(&set, SIGRTMIN);
    sigprocmask(SIG_BLOCK, &set, &oldset);

    sigaction(SIGRTMIN, &(struct sigaction){ .sa_sigaction = handler,
                                             .sa_flags = SA_SIGINFO }, NULL);
    pid_t P = getpid();
    pid_t H1 = fork();          if (H1 < 0) perror("H1"), exit(1);
    if (H1 == 0)
    {
        // use sigqueue() instead of kill(), so can pass sender ID
        sigqueue(P, SIGRTMIN, (union sigval){.sival_ptr = "H1"});
        sigsuspend(&oldset);
        exit(0);
    }
    pid_t H2 = fork();          if (H2 < 0) perror("H2"), exit(1);
    if (H2 == 0)
    {
        pid_t N2 = fork();      if (N2 < 0) perror("N2"), exit(1);
        if (N2 == 0)
        {
            sigqueue(H1, SIGRTMIN, (union sigval){.sival_ptr = "N2"});
            sigsuspend(&oldset);
            exit(0);
        }
        sigqueue(N2, SIGRTMIN, (union sigval){.sival_ptr = "H2"});
        sigsuspend(&oldset);
        exit(0);
    }
    sigqueue(H2, SIGRTMIN, (union sigval){.sival_ptr = "P"});
    pid_t H4 = fork();          if (H4 < 0) perror("H4"), exit(1);
    if (H4 == 0)
    {
        sigqueue(P, SIGRTMIN, (union sigval){.sival_ptr = "H4"});
        sigsuspend(&oldset);
        exit(0);
    }
    pid_t H3 = fork();          if (H3 < 0) perror("H3"), exit(1);
    if (H3 == 0)
    {
        pid_t N3 = fork();      if (N3 < 0) perror("N3"), exit(1);
        if (N3 == 0)
        {
            sigqueue(H4, SIGRTMIN, (union sigval){.sival_ptr = "N3"});
            sigsuspend(&oldset);
            exit(0);
        }
        sigqueue(N3, SIGRTMIN, (union sigval){.sival_ptr = "H3"});
        sigsuspend(&oldset);
        exit(0);
    }
    sigqueue(H3, SIGRTMIN, (union sigval){.sival_ptr = "P"});
    sigprocmask(SIG_UNBLOCK, &set, NULL);
    do ; while (wait(NULL) > 0 || errno != ECHILD);
}

示例输出:

1074 收到来自 1072 P 的信号 1072 收到来自 1073 H1 的信号 1072 收到来自 1076 H4 的信号 1075 收到来自 1074 H2 的信号 1073 收到来自 1075 N2 的信号 1077 收到来自 1072 P 的信号 1076 收到来自 1078 N3 的信号 1078 收到来自 1077 H3 的信号

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-09
    • 2015-08-03
    • 1970-01-01
    相关资源
    最近更新 更多