waitpid文档翻译和使用指南(06/13未完待续)

一、waitpid函数作用和表达式

1)函数作用

1)wait for a child process to terminate or stop, and determine its status. These functions are declared in the header file sys/wait.h.
2)used to request status information from a child process whose process ID is pid. Normally, the calling process is suspended(不加WNOHANG宏定义会阻塞) until the child process makes status information available by terminating.

2)函数表达式和参数

pid_t waitpid (pid_t pid, int *status-ptr, int options);
  • pid
①A value of -1 or WAIT_ANY requests status information for any child process; 
-1或宏定义WAIT_ANY表示询问任何子进程
②a value of 0 or WAIT_MYPGRP requests information for any child process in the same process group as the calling process
0或WAIT_MYPGRP表示询问同一组下的子进程
③Any other negative value - pgid requests information for any child process whose process group ID is pgid
pid<-1
等待进程组号为pid绝对值的任何子进程。
  • options

  • status
    这个参数将保存子进程的状态信息,有了这个信息父进程就可以了解子进程为什么会推出,是正常推出还是出了什么错误。如果status不是空指针,则状态信息将被写入
    器指向的位置。当然,如果不关心子进程为什么推出的话,也可以传入空指针。
    Linux提供了一些非常有用的宏来帮助解析这个状态信息,这些宏都定义在sys/wait.h头文件中。主要有以下几个:
    在这里插入图片描述

二、返回值

1)waitpid代码使用举例

//获取子进程的结束状态,防止单独kill子进程时子进程变成僵尸进程
static void ngx_process_get_status(void)
{
    pid_t            pid;
    int              status;
    int              err;
    int              one=0; //抄自官方nginx,应该是标记信号正常处理过一次

    //当你杀死一个子进程时,父进程会收到这个SIGCHLD信号。
    for ( ;; ) 
    {
        //waitpid,有人也用wait,但掌握和使用waitpid即可;这个waitpid说白了获取子进程的终止状态,这样,子进程就不会成为僵尸进程了;
        //第一次waitpid返回一个> 0值,表示成功,后边显示 2019/01/14 21:43:38 [alert] 3375: pid = 3377 exited on signal 9【SIGKILL】
        //第二次再循环回来,再次调用waitpid会返回一个0,表示子进程还没结束,然后这里有return来退出;
        pid = waitpid(-1, &status, WNOHANG); //第一个参数为-1,表示等待任何子进程,
                                              //第二个参数:保存子进程的状态信息(大家如果想详细了解,可以百度一下)。
                                               //第三个参数:提供额外选项,WNOHANG表示不要阻塞,让这个waitpid()立即返回        

        if(pid == 0) //子进程没结束,会立即返回这个数字,但这里应该不是这个数字【因为一般是子进程退出时会执行到这个函数】
        {
            return;
        } //end if(pid == 0)
        //-------------------------------
        if(pid == -1)//这表示这个waitpid调用有错误,有错误也理解返回出去,我们管不了这么多
        {
            //这里处理代码抄自官方nginx,主要目的是打印一些日志。考虑到这些代码也许比较成熟,所以,就基本保持原样照抄吧;
            err = errno;
            if(err == EINTR)           //调用被某个信号中断
            {
                continue;
            }

            if(err == ECHILD  && one)  //没有子进程
            {
                return;
            }

            if (err == ECHILD)         //没有子进程
            {
                ngx_log_error_core(NGX_LOG_INFO,err,"waitpid() failed!");
                return;
            }
            ngx_log_error_core(NGX_LOG_ALERT,err,"waitpid() failed!");
            return;
        }  //end if(pid == -1)
        //-------------------------------
        //走到这里,表示  成功【返回进程id】 ,这里根据官方写法,打印一些日志来记录子进程的退出
        one = 1;  //标记waitpid()返回了正常的返回值
        if(WTERMSIG(status))  //获取使子进程终止的信号编号
        {
            ngx_log_error_core(NGX_LOG_ALERT,0,"pid = %P exited on signal %d!",pid,WTERMSIG(status)); //获取使子进程终止的信号编号
        }
        else
        {
            ngx_log_error_core(NGX_LOG_NOTICE,0,"pid = %P exited with code %d!",pid,WEXITSTATUS(status)); //WEXITSTATUS()获取子进程传递给exit或者_exit参数的低八位
        }
    } //end for
    return;
}

2)返回值解释

  • (1)waitpid的返回值类别区分
1)返回值大于0:若执行成功则返回子进程的进程ID
2)返回值为0:若定义了WNOHANG参数到options里面,而且有子进程还在运行
3)返回值为-1:表示有错误产生
  • (2)若发生错误,用errno表示错误的区别
err = errno
1)err == EINTR
调用被其他SIGCHLD信号中断,或没设置WNOHANG然后捕捉到其他非屏蔽的信号
2)err == ECHILD
没有想要等待的子进程
((This can happen for one's own child if the action for SIGCHLD is set to SIG_IGN. See also the Linux Notes section about threads.))
3)err == EINVAL
options参数不合法

三、原理备注

翻译来自linux man手册

1)翻译内容

  • 备注
1)init:  linux内核启动后运行的首个用户进程
2)daemon process 守护进程
  • 翻译(段一)
    1)一个子进程即将终结,但是成为子进程后还没被wait函数调用,内核会为其维护一个数据集保留其信息,信息包括pid、终结信息、资源使用情况(PID, termination status, resource usage information),这都是为了便利于父进程后面调用wait函数去获得子进程的数据信息。只要子进程还没被系统调用wait移除,它会消耗内核进程表的槽位,而且只要这个槽位满了,就不能创建更多进程了;但是如果父进程终结了,init这个第一个用户进程就会自动调用wait去移除这些所有的僵尸进程
  • 翻译(段二)
    POSIX.1-2001标注了,如果对信号SIGCHLD的处理是SIG_IGN(忽略)或用sigaction在SIGCHLD上标注SA_NOCLDWAIT,那么这时候子进程就不会变成僵尸子进程,这时候在调用wait() or waitpid() 会阻塞到所有子进程都终结后才继续往下运行

2)原文

  • 段一
    A child that terminates, but has not been waited for becomes a “zombie”. The kernel maintains a minimal set of information about the zombie process (PID, termination status, resource usage information) in order to allow the parent to later perform a wait to obtain information about the child. As long as a zombie is not removed from the system via a wait, it will consume a slot in the kernel process table, and if this table fills, it will not be possible to create further processes. If a parent process terminates, then its “zombie” children (if any) are adopted by init(8), which automatically performs a wait to remove the zombies.

  • 段二
    POSIX.1-2001 specifies that if the disposition of SIGCHLD is set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD (see sigaction(2)), then children that terminate do not become zombies and a call to wait() or waitpid() will block until all children have terminated, and then fail with errno set to ECHILD. (The original POSIX standard left the behavior of setting SIGCHLD to SIG_IGN unspecified. Note that even though the default disposition of SIGCHLD is “ignore”, explicitly setting the disposition to SIG_IGN results in different treatment of zombie process children.) Linux 2.6 conforms to this specification. However, Linux 2.4 (and earlier) does not: if a wait() or waitpid() call is made while SIGCHLD is being ignored, the call behaves just as though SIGCHLD were not being ignored, that is, the call blocks until the next child terminates and then returns the process ID and status of that child.

四、

五、

五、文档链接

1)https://www.gnu.org/software/libc/manual/html_node/Process-Completion.html
2)https://linux.die.net/man/2/waitpid
3)
4)
5)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值