实现思路
- 创建子进程:使用
fork()
函数创建多个子进程。
- 模拟除零错误:在其中一个子进程中进行除零操作,触发异常。
- 父进程等待子进程结束:父进程使用
waitpid()
函数等待每个子进程结束,并获取子进程的退出状态。
- 分析异常原因:通过检查子进程的退出状态,判断是否是因为信号导致的异常终止,并确定异常原因。
关键代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define CHILD_PROCESSES 3
int main() {
pid_t pids[CHILD_PROCESSES];
int status;
for (int i = 0; i < CHILD_PROCESSES; i++) {
pids[i] = fork();
if (pids[i] == -1) {
perror("fork");
return 1;
} else if (pids[i] == 0) {
// 子进程
if (i == 1) {
// 模拟除零错误
int a = 1 / 0;
}
exit(i);
}
}
// 父进程
for (int i = 0; i < CHILD_PROCESSES; i++) {
pid_t terminated_pid = waitpid(pids[i], &status, 0);
if (terminated_pid == -1) {
perror("waitpid");
return 1;
}
if (WIFEXITED(status)) {
printf("子进程 %d 正常退出,退出状态: %d\n", terminated_pid, WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("子进程 %d 异常终止,信号: %d\n", terminated_pid, WTERMSIG(status));
}
}
return 0;
}
waitpid()函数的使用场景和优势
- 使用场景:
- 当需要等待特定子进程结束时,
waitpid()
函数可通过指定子进程的PID来等待。
- 若要在等待子进程时设置非阻塞模式,以便在子进程未结束时继续执行其他任务,
waitpid()
函数可通过设置选项实现。
- 优势:
- 相比
wait()
函数,waitpid()
可等待指定的子进程,而wait()
只能等待任意一个子进程结束。
waitpid()
提供了更灵活的等待方式,如非阻塞等待,通过设置options
参数为WNOHANG
可实现。若子进程未结束,waitpid()
不会阻塞父进程,而是立即返回0,父进程可继续执行其他代码。而wait()
函数会一直阻塞父进程,直到有子进程结束。