pid_t wait(int * statloc);
pid_t waitpid(pid_t pid, int *statloc, int options);
两 个函数都返回两个值:函数的返回值和终止的子进程ID,而子进程终止的状态则是通过statloc指针返回的。wait&waitpid的区别是显而易见 的,wait等待第一个终止的子进程,而waitpid则可以指定等待特定的子进程。这样的区别可能会在下面这种情况时表现得更加明显:当同时有5个客户 连上服务器,也就是说有五个子进程分别对应了5个客户,此时,五个客户几乎在同时请求终止,这样一来,几乎同时,五个FIN发向服务器,同样的,五个 SIGCHLD信号到达服务器,然而,UNIX的信号往往是不会排队的,显然这样一来,信号处理函数将只会执行一次,残留剩余四个子进程作为僵尸进程驻留 在内核空间。此时,正确的解决办法是利用waitpid(-1, &stat, WNOHANG)防止留下僵尸进程。其中的pid为-1表明等待任一个终止的子进程,而WNOHANG选择项通知内核在没有已终止进程项时不要阻塞。

 对于w a i t p i d的p i d参数的解释与其值有关:
      • pid == -1 等待任一子进程。于是在这一功能方面w a i t p i d与w a i t等效。
      • pid > 0 等待其进程I D与p i d相等的子进程。
      • pid == 0 等待其组I D等于调用进程的组I D的任一子进程。
      • pid < -1 等待其组I D等于p i d的绝对值的任一子进程。
    w a i t p i d返回终止子进程的进程I D,而该子进程的终止状态则通过s t a t l o c返回。对于w a i t,其唯一的出错是调用进程没有子进程(函数调用被一个信号中断时,也可能返回另一种出错。但是对于w a i t p i d,如果指定的进程或进程组不存在,或者调用进程没有子进程都能出错。
当一个进程正常或异常终止时,内核就向其父进程发送S I G C H L D信号。因为子进程终止是个异步事件(这可以在父进程运行的任何时候发生),所以这种信号也是内核向父进程发的异步通知。父进程可以忽略该信号,或者提供 一个该信号发生时即被调用执行的函数(信号处理程序)。对于这种信号的系统默认动作是忽略它。调用w a i t或w a i t p i d的进程可能会:
          • 阻塞(如果其所有子进程都还在运行)。
          • 带子进程的终止状态立即返回(如果一个子进程已终止,正等待父进程存取其终止状态)。
          • 出错立即返回(如果它没有任何子进程)。
    如果进程由于接收到S I G C H L D信号而调用w a i t,则可期望w a i t会立即返回。但是如果在一
个任一时刻调用w a i t,则进程可能会阻塞。

例子:

void sig_chld(int signo) 

    int stat;
    pid_t pid;
   
    pid = waitpid(-1, &stat, WNOHANG);
    printf("SIGCHLD: child pid=%d\n",(int)pid);
}

void main()
{
    //....
    signal(SIGCHLD, HandleChild);
    //....
}

posted on 2011-09-30 16:35  眼里的圈圈  阅读(729)  评论(0编辑  收藏  举报