【发布时间】:2010-10-12 12:16:17
【问题描述】:
在我的程序中,我根据用户输入 fork() 多次。
在某些情况下,我想处理 SIGCHLD 并说出类似“进程 # 完成”之类的内容。但在其他情况下,我想忽略此信号。
我该怎么做?
【问题讨论】:
在我的程序中,我根据用户输入 fork() 多次。
在某些情况下,我想处理 SIGCHLD 并说出类似“进程 # 完成”之类的内容。但在其他情况下,我想忽略此信号。
我该怎么做?
【问题讨论】:
你想捕捉信号 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,那么进程表将被僵尸填满。
【讨论】:
为进程全局设置信号处理。如果您想在某些子节点终止但其他子节点不终止时捕获像 SIGCHLD 这样的异步信号,您不能决定提前忽略它。
您需要每次在父级中处理信号,然后决定是否要在处理程序中忽略它。
至少,您的处理程序应该对子进程(siginfo_t 结构中的 si_pid)执行 wait() 以获取其返回码。此时,您可以检查进程 ID 并决定还要做什么。如果您不想打印,则无需打印任何内容。
【讨论】: