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。