在我的程序中,我根据用户输入多次fork()。
在某些情况下,我想处理SIGCHLD并说出“Process#Finished”之类的内容。但在其他情况下,我想忽略这个信号。
我该怎么做?
答案 0 :(得分:4)
为流程全局设置信号处理。如果你想在某些孩子终止而不是其他孩子的情况下捕获像SIGCHLD这样的异步信号,你就不能事先决定忽略它。
您需要每次在父级中处理信号,然后决定是否要在处理程序中忽略它。
至少,您的处理程序应该对子进程执行wait()(siginfo_t结构中的si_pid)以获取其返回代码。此时,您可以检查进程ID并确定还要做什么。如果你不想,你不必打印任何东西。
答案 1 :(得分:3)
您希望捕获信号SIGCHLD然后调用函数。您想使用signal()
执行此操作(man signal
)。在下面的示例中,在捕获信号SIGCHLD之后调用child_died()
(此时子进程已停止)。如果有需要从子项传递给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()
,你需要一种方法将数据从子进程传输到父进程。
我希望这会有所帮助。可能有更好或更简单的方法来完成我不知道的事情。如果有,请发表评论。
答案 2 :(得分:2)
您可以在阻塞或非阻塞模式下使用waitpid
功能来等待来自给定孩子的信号,然后进行一些处理。事实上,你有使用某种类型的wait
,正如格雷厄姆在答案中所述......
答案 3 :(得分:0)
如果忽略SIGCHLD,那么进程表将填满僵尸。