在我的程序中,我根据用户输入 fork() 几次。
在某些情况下,我想处理 SIGCHLD 并说出类似“Process #Finished”之类的内容。但在其他情况下,我想忽略这个信号。
我怎样才能做到这一点?
信号处理是为进程全局设置的。如果您想在某些孩子终止但其他孩子不终止时捕获像 SIGCHLD 这样的异步信号,您不能决定提前忽略它。
您每次都需要在父级中处理信号,然后决定是否要在处理程序中忽略它。
至少,您的处理程序应该对子项(siginfo_t 结构中的 si_pid)执行 wait() 以获取其返回码。此时,您可以检查进程 ID 并决定还要做什么。如果您不想打印,则无需打印任何内容。
你想捕捉信号 SIGCHLD 然后调用一个函数。您想使用signal()
( ) 来执行此操作man signal
。在下面的示例child_died()
中,在捕获信号 SIGCHLD 后调用(此时子进程已死)。如果您需要将信息从子级传递给child_died()
需要条件的父级,则需要使用管道 ( man pipe
)。这是信号和管道的示例:
#include <signal.h>
#include <strings.h>
#include <stdio.h>
#define MAX_SIZE 256
void child_died(int);
int fd[2];
int main()
{
int pid;
extern int fd[];
char *str;
pipe(fd);
signal(SIGCHLD, child_died);
if ((pid = fork()) < 0) {
// error
printf("Error\n");
} else if (pid == 0) {
// child
printf("In child process\n");
close(fd[0]);
str = strdup("Message from child process.\n");
write(fd[1], str, strlen(str) + 1);
} else {
// parent
wait();
printf("Now in parent\n");
}
return 0;
}
void child_died(int s)
{
char *str;
close(fd[1]);
read(fd[0], str, MAX_SIZE);
printf("%s", str);
}
保存为 sigchld.c 并编译:gcc -Wall sigchld.c -o sigchld
如果您想将一个 int(如子 pid)或其他一些数据类型从子进程传递给父进程,您要么必须将其转换为字符串并再次返回,要么找到另一种方法。
如果您想忽略 SIGCHLD,那么在我的示例中,您可以将该逻辑放入child_died()
. 只需使用一个简单的if
. 我不知道您如何决定何时忽略信号以及何时打印您想要的内容,这就是我在上面的代码中包含管道内容的原因。我想你会使用来自子进程的一些信息,并且由于child_died()
在父进程上调用,你需要一种将数据从子进程传输到父进程的方法。
我希望这有帮助。可能有更好或更简单的方法来实现这一点,我不知道。如果有那么请发表评论。
您可以waitpid
在阻塞或非阻塞模式下使用函数来等待来自给定子节点的信号,然后进行一些处理。实际上,您必须使用wait
某种方式,正如格雷厄姆的回答中所述...
如果您忽略 SIGCHLD,那么进程表将充满僵尸。