我试图回答这个问题:
编写一个创建两个子级的程序 C。第二个子进程 被阻止,直到接收到信号SIGUSR1从 父进程。虽然第一个子进程被阻止,直到 SIGUSR2接收从 第二个子进程。终止后终止父级 他的孩子。
但是,执行在下面的代码中没有按预期工作,并且仅显示父printf
。你能告诉我我的代码有什么问题吗?
我的代码:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
void this(int sig) {
printf("this is this");
}
int main() {
int pid = fork();
int pid2;
if (pid < 0) {
exit(-1);
} else if (pid == 0) {
printf("FIrst child is paused");
pause();
printf("ERror");
} else {
pid2 = fork();
if (pid2 < 0) {
exit(-2);
} else if (pid2 == 0) {
signal(SIGUSR1, &this);
printf("Second child is paused");
pause();
kill(pid,SIGUSR2);
printf("signal sent to first child");
} else {
printf("this is the parent");
kill(pid2, SIGUSR1);
printf("signal sent to second child");
wait(NULL);
exit(-3);
}
}
}
您没有做出任何规定来确保仅当第二个孩子准备好时,才会将父母的信号传递给第二个孩子。 由于进程启动需要一些时间,因此信号确实会更快地传递。 在这种情况下,第二个子项将被终止(默认处置SIGUSR1
),或者它将在pause()
中无限期阻塞(如果在安装处理程序之后但在pause
ing 之前收到信号)。 在这两种情况下,第二个孩子都不会向第一个孩子发出信号。
信号掩码和信号处置是通过分叉继承的,因此您可以通过在分叉之前阻止父级中的SIGUSR1
来解决这个问题,然后在子级中使用sigsuspend()
而不是pause()
,这将使您能够原子地取消阻塞信号并开始等待它。
对于第一个孩子来说,这不是问题,因为您正在寻找它来执行SIGUSR2
(终止)的默认处置,并且对于指定的行为,无论这发生在该孩子到达或阻止之前pause()
都无关紧要。
此外,
父母只等待一个孩子,但提示似乎说它必须等待两个孩子。 也许你放弃了第二个
wait()
,因为父母没有终止,但如果是这样,那就是其中一个孩子没有终止的缺失线索。printf
不是异步信号安全的,因此从信号处理程序调用它会调用未定义的行为。您应该在
printf
格式的末尾放置换行符。 这将使您的输出更具可读性,并且还将确保输出及时传递到屏幕。 这最终可能会在您调试时有用。 或者,使用puts()
而不是printf()
,因为您只输出固定字符串。puts()
将自动添加换行符。没有换行符可能解释了为什么第一个孩子在
pause
s 之前的输出永远不会打印。 如果第二个孩子达到无限期pause
状态,那么这也解释了为什么那个孩子的pause
前输出没有被打印出来。