所以我只需要按照一定的顺序创建它们,所以在创建它们的那一刻,它们将发送信号的进程的 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 的信号