头图

过用wait和waitpid函数清理僵尸进程,父进程可以阻塞等待子进程结束,也可以非
阻塞地查询是否有子进程结束等待清理(也就是轮询的方式)。采用第一种方式,父进程阻塞
了就不能处理自己的工作了;采用第二种方式,父进程在处理自己的工作的同时还要记得时不
时地轮询一下,程序实现复杂。
其实,子进程在终止时会给父进程发SIGCHLD信号,该信号的默认处理动作是忽略,父进程可以
自定义SIGCHLD信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子
进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可。

**请编写一个程序完成以下功能:父进程fork出子进程,子进程调用exit(2)终止,父进程自定
义SIGCHLD信号的处理函数,在其中调用wait获得子进程的退出状态并打印。**
  1 #include <unistd.h>
  2 #include <stdlib.h>
  3 #include <signal.h>
  4 #include <stdio.h>
  5 #include <sys/types.h>
  6 #include <sys/wait.h>
  7 
  8 pid_t pid;//全局变量,sigchld和main函数都要访问
  9 
 10 void sig_chld(int signo){//信号处理函数
 11         int stat_val;//该值由获取到的pid值来决定内容
 12         waitpid(pid,&stat_val,0);//0代表不需要第三个参数作用
 13         if(WIFEXITED(stat_val))
 14                 printf("child exited with code %d\n", WEXITSTATUS(stat_val));
 15 //WIFEXITED(status) 若此值为非0 表明进程正常结束。
 16 //若上宏为真,此时可通过WEXITSTATUS(status)获取进程退出状态(exit时参数)
 17         else if(WIFSIGNALED(stat_val))
 18                 printf("Child terminated abnormally, signal %d\n", WTERMSIG(stat_val));
 19 //WIFSIGNALED(status)为非0 表明进程异常终止。
 20 //若上宏为真,此时可通过WTERMSIG(status)获取使得进程退出的信号编号
 21 }
 22 
 23 int main(void){
 24         struct sigaction newact,oldact;
 25 //内核头文件中,struct sigaction 结构体定义在kernel/include/asm/signal.h,此头文件又被kernel/include/linux/signal.h包
    含。
 26 //用户空间的头文件而言,struct sigaction定义在 /usr/include/bits/sigaction.h,此头文件又被/usr/include/signal.h包含
 27         newact.sa_handler = sig_chld;//此处sa_handler是一个函数指针,接收一个函数名(sig_chld)
 28         sigemptyset(&newact.sa_mask);//初始化屏蔽字
 29         newact.sa_flags = 0;//初始化
 30         sigaction(SIGCHLD,&newact,&oldact);//把前面的newact内容备份到oldact
 31 
 32         pid = fork();
 33         if(pid < 0){
 34                 perror("fork");
 35                 exit(1);
 36         }
 37         if(pid > 0)//父进程返回子进程pid,>0表示为父进程        /* parent */
 38         {
 39                 while (1);
 40         }else{//fork调用后,父子进程各返回一次,但顺序不确定,pid==0 /* child */
 41                 exit(2);
 42         }
 43         sigaction(SIGCHLD,&oldact,NULL);//再备份回来,oldact非空,根据他来修改信号处理动作
 44         return 0;
 45 }
 46 

用的vscode远程连接centos7环境,因为vim以及linux里面调试太难用了啊啊啊啊

linux环境下运行结果如下:
image.png


沐小轲
9 声望0 粉丝

C++初学者