实现思路
- 创建子进程:使用
fork()
函数创建多个子进程。
- 父进程等待子进程结束:父进程使用
waitpid()
函数等待子进程结束。waitpid()
函数可以阻塞等待指定子进程结束,并获取子进程的退出状态。
- 处理子进程异常退出:通过检查
waitpid()
返回的子进程退出状态来判断子进程是否是由于信号导致的异常退出。如果是,提取导致异常退出的信号编号。
- 信号处理:可以注册信号处理函数,在子进程异常退出时进行额外的处理。
关键代码片段
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
void sigchld_handler(int signum) {
pid_t pid;
int status;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
if (WIFSIGNALED(status)) {
printf("Child %d terminated by signal %d\n", pid, WTERMSIG(status));
} else {
printf("Child %d exited normally with status %d\n", pid, WEXITSTATUS(status));
}
}
}
int main() {
int num_children = 3;
for (int i = 0; i < num_children; i++) {
pid_t pid = fork();
if (pid == 0) {
// 子进程
if (i == 1) {
// 模拟异常退出
raise(SIGABRT);
}
exit(0);
} else if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
}
// 注册信号处理函数
struct sigaction sa;
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(EXIT_FAILURE);
}
// 父进程等待所有子进程结束
while (wait(NULL) > 0);
return 0;
}
代码解释
sigchld_handler
函数:处理 SIGCHLD
信号,在子进程结束时被调用。通过 waitpid()
函数获取子进程的退出状态,并判断是正常退出还是异常退出。
main
函数:
- 使用
fork()
创建多个子进程。
- 注册
SIGCHLD
信号的处理函数 sigchld_handler
。
- 父进程通过
wait(NULL)
等待所有子进程结束。