SIGCHLD信号与父进程异步等待子进程

阻塞式等待:wait函数,当然waitpid函数当其第三个参数不为WNOHANG时也是阻塞式等待。
非阻塞式等待:(轮询的方式):当waitpid函数当其第三个参数为WNOHANG是非阻塞式等待。

父进程可以阻塞等待子进程结束,也可以非阻塞地查询是否有子进程结束等待清理(也就是轮询的方式)。
若采用阻塞等待方式,父进程就不能处理自己的工作了;采用非阻塞方式,父进程在处理自己工作的同时还要时不时地轮询⼀下子进程状态,程序实现复杂。

SIGCHLD信号:SIGCHLD是l第17号信号.
事实上,进程等待并不是像上边说的那样,而是子进程在终止时会向父进程发SIGCHLD信号,该信号的默认动作是忽略,父进程便可以自定义SIGCHLD信号的处理函数,这样它只需专心处理自己的工作,而不必关⼼子进程了, 子进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可。

下面来进程编程验证:
1.先来编写子进程退出时会给父进程发送SIGCHLD信号的机制:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<signal.h>
  4 
  5 void handler(int signo)
  6 {
  7         int count=10;
  8         while(count--){
  9                 printf("get a %d sig,pid:%d\n",signo,getpid());
 10                 sleep(1);
 11         }
 12 }
 13 int main()
 14 {
 15         pid_t pid=fork();
 16         if(pid<0){
 17                 perror("fork()");
 18         }
 19         else if(pid==0){//child
 20                 printf("child:%d\n",getpid());
 21                 exit(1);
 22         }
 23         else{//father
 24               signal(SIGCHLD,handler);//父进程捕捉子进程退出时发出的17号信号
 25                 waitpid(-1,NULL,0);//父进程等待子进程退出
 27         }
 28         return 0;
 29 }

这里写图片描述

2.父进程异步等待子进程(即为轮询式等待)
上边父进程在等待子进程成功后直接退出,现在我们要实现父进程等待子进程成功后,继续做自己的事情。这就是异步等待。下面我们用非阻塞式等待(轮询的方式)。

下面来解释代码:

这里写图片描述

这里写图片描述

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<signal.h>
  4 
  5 void handler(int signo)
  6 {
  7         while(waitpid(-1,NULL,WNOHANG)>0){
  8                 printf("get a %d sig,pid:%d\n",signo,getpid());//getpid()为父进程的id
  9         }
 10         printf("child is quit\n",getpid());
 11 }
 12 int main()
 13 {
 14         pid_t pid=fork();
 15         if(pid<0){
 16                 perror("fork()");
 17         }
 18         else if(pid==0){//child
 19                 printf("child:%d\n",getpid());
 20                 exit(1);
 21         }
 22         else{//father
 23 
 24                 signal(SIGCHLD,handler);
 25                 while(1){
 26                         printf("father %d proc is doing something\n",getpid());
 27                         sleep(1);
 28                 }
 29         }
 30         return 0;
 31 }
 32 

结果展示:
这里写图片描述
可以看出实现了父进程对子进程的异步等待。

猜你喜欢

转载自blog.csdn.net/xiaodu655/article/details/80260948