1. 函数介绍

  wait函数:调用该函数使进程阻塞,直到任意一个子进程结束,或者该进程接收到了一个信号为止,如果该进程没有子进程或该进程的子进程已经结束,wait函数立即返回。

  waitpid函数:与wait函数类似,但可以指定子进程的PID以及等待方式(阻塞和非阻塞)。

  他们的函数原型如下:

pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);

函数参数:

  status是一个int型的指针,表示程序退出时的状态,如果传入NULL则表示不关心程序退出时的状态。

  传入的pid的值有好几种不同的情况:

    pid > 0:要等待退出的子进程PID;

    pid = -1:等待任意一个子进程退出;

    pid = 0:等待其组ID等于调用进程的组ID的任意子进程;

    pid < -1:等待其组ID等于pid的绝对值的任意子进程。

  options:

    WNOHANG:若由pid指定的子进程并不立即可用,则waitpid不阻塞,此时返回值为0。

    WUNTRACED:若某实现支持作业控制,则有pid指定的任一子进程状态已暂停,且其状态自暂停以来还没报告过,则返回其状态。(该选项不常用)。

    0:同wait,阻塞父进程,等待子进程退出。

    其中WNOHANG和WUNTRACED可以通过 “|” 运算符连接。

  实际上wait就是封装后的waitpid:

static inline pid_t wait(int * wait_stat)
{
    return waitpid(-1, wait_stat, 0);
}

返回值:

  正常:结束的子进程的ID号,使用选项WNOHANG而没有子进程结束时返回0,调用出错返回-1。

2. 测试用例

  测试代码:

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <sys/wait.h>
 4 
 5 int main(int argc, const char *argv[])
 6 {
 7     int pid;
 8     int wait_ret = 0;
 9     
10     pid = fork();
11 
12     if(pid == 0) {              /* 子进程 */
13         printf("#############\n");
14         printf("I'm child\n\n");
15         printf("My PID = %d\n", getpid());
16         sleep(2);
17         printf("I'm dead\n");
18     } else if (pid > 0) {       /* 父进程 */
19         printf("#############\n");
20         printf("I'm parent\n");
21         printf("wait...\n");
22         wait_ret = wait(NULL);
23         printf("wait_ret = %d\n", wait_ret);
24     }
25 
26     return 0;
27 }

  测试结果:

 

   从测试结果可以看出,wait函数阻塞了,等子进程结束之后才继续,并且得到的返回值正是子进程的PID。

  接下来换waitpid的测试程序:

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <sys/wait.h>
 4 
 5 int main(int argc, const char *argv[])
 6 {
 7     int pid;
 8     int wait_ret = 0;
 9     
10     pid = fork();
11 
12     if (pid == 0) {              /* 子进程 */
13         printf("#############\n");
14         printf("I'm child\n\n");
15         printf("My PID = %d\n", getpid());
16         sleep(3);
17         printf("I'm dead\n");
18     } else if (pid > 0) {       /* 父进程 */
19         printf("#############\n");
20         printf("I'm parent\n");
21         while (1) {
22             wait_ret = waitpid(pid, NULL, WNOHANG);
23             printf("wait_ret = %d\n", wait_ret);
24             sleep(1);
25             if (wait_ret != 0) {
26                 printf("Child dead\n");
27                 break;
28             }
29         }
30     }
31 
32     return 0;
33 }

  测试结果:

  

 

 

   从结果可以看出,由于传入了WNOHANG,因此waitpid函数不阻塞,在子进程没有退出的时候waitpid返回0,在子进程退出之后waitpid返回的是子进程的PID。