ocean2811
12/22/2017 - 9:30 AM

Linux僵尸进程处理 wait 与waitpid 用法,信号捕捉与屏蔽int sigaction( int signum, const struct sigaction *act, struct sigaction *oldact );

1.Linux C/C++ 编程,子进程退出时避免成为僵尸进程的方法 与 处理僵尸进程方法。 2.wait与waitpid 用法 3.信号捕捉与屏蔽int sigaction( int signum, const struct sigaction *act, struct sigaction *oldact);

\!h /*调用wait()或者waitpid(),通知内核回收僵尸进程*/

//阻塞当前进程等待子进程退出并回收子进程
pid_t wait(int *status);
//参数int *status : 子进程的退出状态,传出参数
//返回值 : 成功返回被收集的子进程的进程ID,当前进程没有子进程调用就会失败,失败返回-1并设置errno为ECHILD。

//相关宏函数
WIFEXITED(int status_num) //这个宏用来指出子进程是否为正常退出的,如果是,它会返回一个非零值.
WEXITSTATUS(int status_num) //当WIFEXITED返回非零值时,我们可以用这个宏来提取子进程的返回值.

//用法:
int status;
pid_t pid;
pid = wait(&status);
if(WIFEXITED(status)) /*如果WIFEXITED返回非零值 */
{
  printf("the child process %d exit normally./n",pid);
  printf("the return code is %d./n",WEXITSTATUS(status));
}
else /* 如果WIFEXITED返回零 */
{
  printf("the child process %d exit abnormally./n",pid);
}


//回收子进程,可自定义参数
pid_t waitpid(pid_t pid,int *status,int options);
//参数pid_t pid :      
//  pid>0时,只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去.
//  pid=-1时,等待任何一个子进程退出,此时waitpid和wait的作用一样.
//  pid=0时,等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬.
//  pid<-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值.
//参数int *status : 子进程的退出状态,传出参数
//参数options : 取值为WNOHANG或WUNTRACED,可以用"|"运算符把它们连接起来使用
//  WNOHANG 如果指定的pid并未结束waitpid将不阻塞等待
//  WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
//返回值 : 
//  当正常返回的时候,waitpid返回收集到的子进程的进程ID.
//  如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0.
//  如果调用中出错,则返回-1,这时errno会被设置.当pid所指示的子进程不存在,或不是调用进程的子进程返回-1,errno=ECHILD

//用法:(回收所有已退出的子进程,直到:出错或无已退出子进程)
void func()
{
    int stat = 0;
    while (1)
    {
        if (waitpid(-1,&stat,WNOHANG)) <= 0)
        {
            if (errno == EINTR)
            {
                //被中断,继续 
                continue;
            }
            //子进程全部收尸完成或出现错误
            break;
        }

        //检测状态
        cout << "stat: " << stat << endl;
        if (WIFEXITED(stat) != 0)//正常退出
        {
            cout << "EXITSTAT: " << WEXITSTATUS(stat) << endl;//打印状态码
        }
        else if (WIFSIGNALED(stat) != 0)//因信号结束
        {
            cout << "SIG: " << WTERMSIG(stat) << endl;//打印信号编号
        }
        else if (WIFSTOPPED(stat) != 0)//被暂停执行
        {
            cout << "SIG: " << WSTOPSIG(stat) << endl;//打印引发子进程暂停的信号代码
        }
        else
        {
            cout << "未知退出状态" << endl;
        }
    }
}
\!h /*父进程忽略SIGCHLD信号 或处理SIGCHLD信号,处理函数可选是否携带用户数据*/

//忽略SIGCHLD信号
struct sigaction sigset;
sigset.sa_flags = 0;
sigemptyset(&sigset.sa_mask);
sigset.sa_handler = SIG_IGN;
sigaction(SIGCHLD, &sigset, NULL);

//处理SIGCHLD信号
void handle(int signum);//请自行定义,此处仅作声明!

struct sigaction sigset;
sigset.sa_flags = 0;
sigemptyset(&sigset.sa_mask);
sigset.sa_handler = handle;   //信号处理函数
sigaction(SIGCHLD, &sigset, NULL);