linux下同时使用wait和SIGCHLD的信号处理函数
前一段时间写代码用到了子进程,设置了SIGCHLD的信号处理函数,并且父进程使用wait等待子进程结束,运行的结果和我想象的不大一样。
原型抽取如下:
/* * SigChld.cpp * * Created on: 2012-11-16 * Author: hf */ #include <iostream> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <signal.h> using namespace std; void fun() { cout << "fun begin" << endl; int n = execl("/home/hf/workspace/Hello/src/tellPid", "ls", NULL); if (-1 == n) { cout << "fun error" << endl; } cout << "fun end" << endl; } void sig_chld(int signo) { pid_t pid; int stat; cout << "in sig_chld" << endl; if (signo == SIGCHLD) { cout << "in sig_chld sigchld" << endl; } while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) { cout << "进程:" << pid << "结束" << endl; } } void sig_chld1(int signo) { pid_t pid; int stat; cout << "in sig_chld1" << endl; if (signo == SIGCHLD) { cout << "in sig_chld1 sigchld" << endl; } while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) { cout << "进程1:" << pid << "结束" << endl; } } int main() { cout << "main begin" << endl; signal(SIGCHLD, sig_chld); signal(SIGCHLD, sig_chld1); int n = fork(); switch (n) { case 0: cout << "child:" << getpid() << endl; sleep(7); fun(); cout << "child end" << endl; exit(0); break; case -1: cout << "fork error" << endl; break; default: cout << "parent,child pid:" << n << endl; break; } int status = 0; int tt = wait(&status); cout << "wait:" << tt << endl; cout << "main end" << endl; }
在父进程中使用wait等待子进程结束,同时设置了SIGCHLD的信号处理函数,此处理函数中使用waitpid来回收资源。
执行的时候发现,wait函数正常执行,并且返回了子进程的pid,信号处理函数也能够进入,但是waitpid函数不在能够收集到子进程的信息。
在网上搜索了一下,在http://www.cnblogs.com/taobataoma/archive/2007/08/30/875743.html发现一些信息:
内核对子进程终止(SIGCLD)信号的处理方法与其他信号有所区别。当进程检查出收到了一个子进程终止的信号时,缺省情况下,该进程 就象没有收到该信号似的,如果父进程执行了系统调用wait,进程将从系统调用wait中醒来并返回wait调用,执行一系列wait调用的后续操作(找 出僵死的子进程,释放子进程的进程表项),然后从wait中返回。SIGCLD信号的作用是唤醒一个睡眠在可被中断优先级上的进程。如果该进程捕捉了这个
信号,就象普通信号处理一样转到处理例程。如果进程忽略该信号,那么系统调用wait的动作就有所不同,因为SIGCLD的作用仅仅是唤醒一个睡眠在可被 中断优先级上的进程,那么执行wait调用的父进程被唤醒继续执行wait调用的后续操作,然后等待其他的子进程。
如果一个进程调用signal系统调用,并设置了SIGCLD的处理方法,并且该进程有子进程处于僵死状态,则内核将向该进程发一个SIGCLD信号。
总结如下:
当父进程阻塞在wait系统调用,子进程结束的时候,内核发送SIGCHLD到进程,父进程从wait调用中醒来,继续执行wait的后续操作(释放僵尸子进程),切换到用户态后,进程执行信号处理函数,此时waitpid已经取不到僵死子进程的信息,所以while里面的语句没有执行。
如果在调试的时候,把断点设置SIGCHLD信号处理函数的while之前,会发现,执行到断点的时候,ps一下,发现根本就没了僵尸进程了。
- 上一篇:没有了
- 下一篇:没有了