SIGINT 被多个进程忽略
SIGINT ignored by multiple processes
我想创建三个进程,它们会打印一些东西,直到我按下 ctrl+c。下面你可以看到我的尝试,但是当尝试停止程序时没有任何反应。当只有一个 child 被分叉时,效果很好。哪里可能有问题?提前致谢。
void my_handler(int s){
printf("Caught signal %d, I am dying\n",s);
exit(1);
}
void doChild(int count){
fprintf(stdout,"Child %d with pid: %d\n",count, getpid());
}
int main(int argc, char **argv){
int count = 0;
pid_t pid;
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = my_handler;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
fprintf(stdout, "Ahoj svjete!\n");
for(;count < 3;count++){
pid = fork();
switch(pid){
case -1:
perror("Fork :(");
exit(EXIT_FAILURE);
case 0:
while(1){
doChild(count);
}
}
}
exit(EXIT_SUCCESS);
}
在此循环中:
for(;count < 3;count++){
pid = fork();
}
你将创建总共 8 个进程,因为你正在执行 fork()
3 次,即 1. 调用 fork()
给你 1* 2=2 个进程,第二次调用 fork()
给你 2*2=4 个进程,第三次调用 fork()
给你 4*2=8 个进程。
此外,您设置信号处理程序的方式会将信号发送到整个 process group (e.g. parent and children). If this is not what you want, you should look at setpgid()
and setsid()
函数,以使每个子进程的信号单独工作。
编辑:
这是您的代码的修改版本,其中包含我添加的一些内容,可帮助您了解正在发生的事情。您还可以在 Chris Dodds 的回答中找到更多关于代码中发生的事情的解释。发送一个信号现在会杀死所有的子进程和父进程,但这段代码只是一个例子,让你了解它是如何工作的(正如我所说,你应该在这里使用进程组)。
void my_handler(int s){
printf("Caught signal %d, I am dying, my PID=%d\n",s, (int)getpid());
exit(1);
}
void doChild(int count){
fprintf(stdout,"Child %d with pid: %d\n",count, getpid());
}
int main(int argc, char **argv){
int count = 0;
int status;
pid_t pid;
for(;count < 2;count++){
pid = fork();
}
printf("My PID=%d\n", (int)getpid());
fprintf(stdout, "Ahoj svjete!\n");
switch(pid){
case -1:
perror("Fork :(");
exit(EXIT_FAILURE);
case 0:
signal(SIGINT, my_handler);
while(1){
doChild(count);
}
default:
printf("Parent\n");
sigignore(SIGINT);
wait(&status);
}
printf("Process %d ended life.\n", (int)getpid());
exit(EXIT_SUCCESS);
}
正如 REACHUS 指出的那样,您得到 8 个进程,而不是 3 个。此外,开关会测试每个进程中 last 分支调用的结果,因此其中 4 个进程会立即退出,而其他 4 个留在 doChild
循环中 运行。
现在因为 top-level 进程(执行第一个 fork 的初始进程)是退出的进程之一(它的 fork
调用所有 return children,从不为 0),shell 再次接管,这意味着当您点击 ctrl-C 时,它会转到 shell 而不是到你的分叉 children。那些 children 永远不会看到 SIGINT(除非你用 kill
明确地将它发送给他们),所以永远不要退出。