SIGCHLD信号

SIGCHLD的产生条件

1、子进程终止时 
2、子进程接收到SIGSTOP信号停止时 
3、子进程处在停止态,接受到SIGCONT后唤醒时

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 #include <errno.h>
  5 #include <sys/types.h>
  6 #include <sys/wait.h>
  7 #include <signal.h>
  8
  9 void sys_err(char *str)
 10 {
 11     perror(str);
 12     exit(1);
 13 }
 14 void do_sig_child(int signo)
 15 {
 16     int status;
 17     pid_t pid;
 18     while ((pid = waitpid(0, &status, WNOHANG)) > 0)
 19     {
 20         if (WIFEXITED(status))
 21             printf("child %d exit %d\n", pid, WEXITSTATUS(status));
 22         else if (WIFSIGNALED(status))
 23             printf("child %d cancel signal %d\n", pid, WTERMSIG(status));
 24     }
 25 }
 26 int main(void)
 27 {
 28     pid_t pid;
 29     int i;
 30
 31     for (i = 0; i < 10; i++)
 32     {
 33         if ((pid = fork()) == 0)
 34         break;
 35         else if (pid < 0)
 36             sys_err("fork");
 37     }
 38
 39     if (pid == 0)
 40     {
 41         int n = 18;
 42         while (n--)
 43         {
 44             printf("child ID %d\n", getpid());
 45             sleep(1);
 46         }
 47         return i;
 48     }
 49     else if (pid > 0)
 50     {
 51         //先设置捕捉
 52         //再解除对SIGCHLD的阻塞
 53         struct sigaction act;
 54         act.sa_handler = do_sig_child;//捕捉函数在上面
 55         sigemptyset(&act.sa_mask);
 56         act.sa_flags = 0;
 57         sigaction(SIGCHLD, &act, NULL);//当SIGCHLD信号到达是调用信号处理函数
 58
 59         while (1)
 60         {
 61             printf("Parent ID %d\n", getpid());
 62             sleep(1);
 63         }
 64     }
 65     return 0;
 66 }
 67
 68
 69
 70 执行结果:
 71 child ID 4170
 72 child ID 4171
 73 child ID 4169
 74 child ID 4172
 75 child ID 4168
 76 child ID 4166
 77 child ID 4165
 78 child ID 4164
 79 child ID 4163
 80 child ID 4170
 81 Parent ID 4162
 82 child ID 4167
 83 child ID 4171
 84 child ID 4169
 85 child ID 4172
 86 child ID 4168
 87 child ID 4166
 88 child ID 4165
 89 child ID 4164
 90 child ID 4163
 91 Parent ID 4162
 92 child 4167 exit 4
 93 child 4170 exit 7
 94 Parent ID 4162
 95 child 4169 exit 6
 96 child 4171 exit 8
 97 Parent ID 4162
 98 child 4168 exit 5
 99 child 4172 exit 9
100 Parent ID 4162
101 child 4166 exit 3
102 Parent ID 4162
103 child 4165 exit 2
104 Parent ID 4162
105 child 4164 exit 1
106 Parent ID 4162
107 child 4163 exit 0
108 Parent ID 4162
109 Parent ID 4162
110 Parent ID 4162
111 ^C
pid_t waitpid(pid_t pid, int *status, int options)
    options
        WNOHANG
            没有子进程结束,立即返回
        WUNTRACED
            如果子进程由于被停止产生的SIGCHLD, waitpid则立即返回
        WCONTINUED
            如果子进程由于被SIGCONT唤醒而产生的SIGCHLD, waitpid则立即返回

    获取status
        WIFEXITED(status)
            子进程正常exit终止,返回真
                WEXITSTATUS(status)返回子进程正常退出值
        WIFSIGNALED(status)
            子进程被信号终止,返回真
                WTERMSIG(status)返回终止子进程的信号值
        WIFSTOPPED(status)
            子进程被停止,返回真
                WSTOPSIG(status)返回停止子进程的信号值
        WIFCONTINUED(status)
            子进程由停止态转为就绪态,返回真
时间: 2024-12-07 23:34:38

SIGCHLD信号的相关文章

SIGCHLD 信号

SIGCHID: 子进程在终止时会给父进程发SIGCHLD信号,该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可. 要想不产生僵尸进程还有另外一种办法:父进程调用sigaction将SIGCHLD的处理动作置为SIG_IGN,这样fork出来的子进程在终止时会自动清理掉,不会产生僵尸进程,也不会通知父进程. 代码:   1 #include<st

unp TCP 客户端服务器回射程序中对SIGCHLD信号的处理

第五章中,有一个例子模拟客户端并发的终止TCP连接,服务器捕捉并处理SIGCHLD信号并调用waitpid函数防止僵死进程的出现.信号处理函数中核心的一句是: 1 while ( (pid = waitpid(-1, &statloc, WNOHANG)) > 0 ) 2 { 3 printf("wait child pid:%ld\n",(long)pid); 4 } 这是在使用wait函数时不能解决N个子进程同时终止时导致只有1个子进程被wait而其他N-1个子进程变

关于SIGCHLD 信号

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

[转] linux下的僵尸进程处理SIGCHLD信号

什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打开的文件等,但内核为每一个终止子进程保存了一定量的信息.这些 信息至少包括进程ID,进程的终止状态,以及该进程使用的CPU时间,所以当终止子进程的父进程调用wait或waitpid时就可以得到这些信息. 而僵尸进程就是指:一个进程执行了exit系统调用退出,而其父进程并没有为它收尸(调用wait或waitpid来获得它的结束状态)的进程. 任何一个子进程(init除外)在exit后并非马上就消失,而是

linux下的僵尸进程处理SIGCHLD信号

什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打开的文件等,但内核为每一个终止子进程保存了一定量的信息.这些信息至少包括进程ID,进程的终止状态,以及该进程使用的CPU时间,所以当终止子进程的父进程调用wait或waitpid时就可以得到这些信息. 而僵尸进程就是指:一个进程执行了exit系统调用退出,而其父进程并没有为它收尸(调用wait或waitpid来获得它的结束状态)的进程. 任何一个子进程(init除外)在exit后并非马上就消失,而是留

waitpid和SIGCHLD信号回收僵尸进程

对于多进程而言,父进程一般需要跟踪子进程的退出状态.因此当子进程结束运行时,内核不会立即释放该进程的进程表的表项.以满足父进程后续对子进程退出的信息查询(死后验尸),当然前提是父进程还在运行.在子进程结束之后,父进程读取其退出状态之前,我们称该子进程处于僵尸态(用户空间已经被释放,其不能被调度). 先介绍两个系统调用函数: #include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status);// wait是一个阻

(转载)linux下的僵尸进程处理SIGCHLD信号Linux环境进程间通信(五): 共享内存(下)

Linux环境进程间通信(五): 共享内存(下) 在共享内存(上)中,主要围绕着系统调用mmap()进行讨论的,本部分将讨论系统V共享内存,并通过实验结果对比来阐述两者的异同.系统V共享内存指的是把所有共享数据放在共享内存区域(IPC shared memory region),任何想要访问该数据的进程都必须在本进程的地址空间新增一块内存区域,用来映射存放共享数据的物理内存页面. 系统调用mmap()通过映射一个普通文件实现共享内存.系统V则是通过映射特殊文件系统shm中的文件实现进程间的共享内

2次使用fork避免产生僵尸进程和不去处理SIGCHLD信号

1.如下代码所示 #include <unistd.h> #include <sys/types.h> #include <unistd.h> int main(int argc,char *argv[]) { pid_t child = fork(); if( child == -1 ) { //error printf("\nfork child error."); exit(0); } else if(child == 0){ //exit(0

僵进程与SIGCHLD信号

参考: https://www.cnblogs.com/webor2006/p/4014586.html wait()和waitpid()的参数解析:https://blog.csdn.net/csdn_kou/article/details/81091191 原文地址:https://www.cnblogs.com/Malphite/p/11703583.html