MST

星途 面试题库

面试题:C语言处理子进程异常退出在Linux下的实现

假设在Linux系统下使用C语言创建多个子进程,要求父进程不仅能正常等待子进程结束,还能处理子进程由于信号导致的异常退出情况,并且获取子进程异常退出时的信号编号。请描述实现思路并给出关键代码片段。
18.6万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 创建子进程:使用 fork() 函数创建多个子进程。
  2. 父进程等待子进程结束:父进程使用 waitpid() 函数等待子进程结束。waitpid() 函数可以阻塞等待指定子进程结束,并获取子进程的退出状态。
  3. 处理子进程异常退出:通过检查 waitpid() 返回的子进程退出状态来判断子进程是否是由于信号导致的异常退出。如果是,提取导致异常退出的信号编号。
  4. 信号处理:可以注册信号处理函数,在子进程异常退出时进行额外的处理。

关键代码片段

#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;
}

代码解释

  1. sigchld_handler 函数:处理 SIGCHLD 信号,在子进程结束时被调用。通过 waitpid() 函数获取子进程的退出状态,并判断是正常退出还是异常退出。
  2. main 函数
    • 使用 fork() 创建多个子进程。
    • 注册 SIGCHLD 信号的处理函数 sigchld_handler
    • 父进程通过 wait(NULL) 等待所有子进程结束。