waitpid()提供了更灵活的选项,允许父进程等待特定的子进程终止,或非阻塞地查询子进程状态,进一步增强了进程管理的灵活性。比如可以指定等待某个pid的子进程、提供一个非阻塞版本的wait()功能等,这对处理多个子进程的情况更加友好。
1.头文件
#include <sys/types.h>
#include <sys/wait.h>
2.函数原型
pid_t waitpid(pid_t pid, int *wstatus, int options);
3.参数
pid:参数的取值
如果pid小于-1:等待任何子进程,其进程组 ID 等于 -pid 的绝对值。
如果pid等于-1:等待任何子进程(与 wait() 的行为相同)。
如果pid等于0:等待任何子进程,其进程组 ID 等于调用进程的进程组 ID。
如果pid大于0:等待指定 PID 的子进程。
wstatus:指向一个整型变量的指针,用于存储子进程的退出状态。如果不需要,可以传 NULL。
options:可选的标志位,通常为 0表示使用默认的阻塞行为,即父进程会阻塞,直到指定的子进程结束,并返回该子进程的状态。常见的其他选项:
WNOHANG:非阻塞模式。如果子进程没有结束,立即返回0。如果子进程已经终止运行,则立即返回该子进程的进程号与状态信息。
WUNTRACED:返回被暂停的子进程状态。
WCONTINUED:如果子进程被继续执行,返回状态。
4.返回值
成功时,返回结束的子进程的 PID。如果没有符合条件的子进程,返回 0(在非阻塞模式下),或者 -1(在阻塞模式下),并设置 errno。
5.示例:使用waitpid()函数回收指定进程资源
| #include <stdio.h>
#include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> int main() { pid_t pid1 = fork(); // 创建第一个子进程 if (pid1 < 0) { perror("fork failed"); exit(EXIT_FAILURE); } else if (pid1 == 0) { // 第一个子进程 printf("First child process (PID: %d) is running...\n", getpid()); sleep(2); // 模拟工作 exit(1); // 返回退出码1 } pid_t pid2 = fork(); // 创建第二个子进程 if (pid2 < 0) { perror("fork failed"); exit(EXIT_FAILURE); } else if (pid2 == 0) { // 第二个子进程 printf("Second child process (PID: %d) is running...\n", getpid()); sleep(3); // 模拟工作 exit(2); // 返回退出码2 } // 父进程等待第一个子进程 int status; pid_t result1 = waitpid(pid1, &status, 0); // 阻塞等待第一个子进程 if (result1 == -1) { perror("waitpid failed"); exit(EXIT_FAILURE); } printf("First child terminated with PID: %d\n", result1); if (WIFEXITED(status)) { printf("First child exited with status %d\n", WEXITSTATUS(status)); } // 使用非阻塞方式等待第二个子进程 pid_t result2 = waitpid(pid2, &status, WNOHANG); if (result2 == 0) { printf("Second child is still running...\n"); } else if (result2 == -1) { perror("waitpid failed"); } else { printf("Second child terminated with PID: %d\n", result2); if (WIFEXITED(status)) { printf("Second child exited with status %d\n", WEXITSTATUS(status)); } } // 等待所有子进程结束 while ((result1 = waitpid(-1, &status, WNOHANG)) > 0) { printf("Processed child with PID: %d\n", result1); if (WIFEXITED(status)) { printf("Child exited with status %d\n", WEXITSTATUS(status)); } else if (WIFSTOPPED(status)) { printf("Child is stopped by signal %d\n", WSTOPSIG(status)); } else if (WIFCONTINUED(status)) { printf("Child has been continued.\n"); } } return 0; } |
6.运行结果
| First child process (PID: 200850) is running...
Second child process (PID: 200851) is running... First child terminated with PID: 200850 First child exited with status 1 Second child is still running... |
7.代码解析
父进程创建两个子进程,分别在模拟工作后退出,并返回不同的退出码。然后使用 waitpid(pid1, &status, 0) 阻塞等待第一个子进程结束,并获取其退出状态,通过exit程序退出之后就不会接着执行后面的程序了。使用 waitpid(pid2, &status, WNOHANG) 非阻塞方式检查第二个子进程的状态,如果仍在运行,父进程会立即返回。最后,父进程通过 waitpid(-1, &status, WNOHANG) 循环等待所有子进程结束,处理每个子进程的状态。
202