我正在研究Linux中的信号,并且试图了解进程的机制。我写了这段代码:
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
void filsFini(int sig){
printf("The Child finished\n");
}
int main(){
pid_t pid;
system("clear");
if((pid=fork())==0){
printf("Child in a break\n");
for(;;);
}
printf("The father %d \n",getpid());
system("ps -lH");
(void) signal(SIGCHLD,filsFini);
printf("hit a button to end\n");
getchar();
kill(pid,SIGINT);
system("ps -lH");
waitpid(pid,NULL,0);
system("ps -lH");
return EXIT_SUCCESS;
}
最后我得到这个结果,我有一个问题是printf("Child finished\n");
被写了两次,我该如何避免呢?
答案 0 :(得分:3)
您每次呼叫system("ps -lH")
都会创建更多的子级,并且也会收到SIGCHLD
的通知。不幸的是,没有任何方法可以控制您收到SIGCHLD
通知的子进程。是全有还是全无。
对于您编写的程序,我建议您什么也不要选择:不要为SIGCHLD
安装处理程序。您可以依靠已经拥有的waitpid
调用,在您直接创建的子进程完成时通知您。 system
将负责为其创建的子进程调用waitpid
;您不必担心它们。
(SIGCHLD
的全有或全无是一个麻烦,因为编写更复杂的程序需要等待子进程完成和异步I / O事件的可变组合,尤其是在涉及库的情况下可能会创建主事件循环不知道的子进程。但是不要担心,直到您到达那里为止。)
答案 1 :(得分:1)
system("ps -lH");
也将呼叫fork()
,请参阅http://man7.org/linux/man-pages/man3/system.3.html
如果只想调用printf("Child finished\n");
一次,则可以在子进程中捕获SIGINT
并将其输出。
以下code
可以工作:
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
void handle_SIGINT(int sig) {
printf("The Child finished\n");
exit(EXIT_FAILURE);
}
int main(){
signal(SIGINT, handle_SIGINT);
pid_t pid;
if ((pid=fork()) == 0) {
printf("Child in a break\n");
for(;;)
;
}
printf("The father %d \n", getpid());
system("ps -lH");
printf("hit a button to end\n");
getchar();
kill(pid, SIGINT);
printf("\nbefore waitpid:\n");
system("ps -lH");
waitpid(pid, NULL, 0);
printf("\nafter waitpid:\n");
system("ps -lH");
return EXIT_SUCCESS;
}