MST

星途 面试题库

面试题:C语言实现Linux下子进程批量等待的复杂场景处理

在Linux系统下,使用C语言编写一个程序,创建多组子进程(每组子进程数量不同且动态变化),并且每组子进程有不同的任务优先级。父进程需要按照优先级顺序依次等待每组子进程完成,同时还要处理子进程可能出现的异常退出(如信号导致的异常终止)情况。详细说明设计思路,包括数据结构的选择、同步机制的运用,并给出完整的代码实现。
35.8万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 数据结构选择
    • 使用结构体来表示每组子进程的相关信息,包括子进程数量、任务优先级以及记录子进程ID的数组。
    • 例如:
typedef struct {
    int num_processes;
    int priority;
    pid_t *pids;
} ProcessGroup;
  1. 同步机制运用
    • 使用waitpid函数来等待子进程结束。父进程需要按照优先级顺序遍历ProcessGroup数组,并依次等待每组子进程完成。
    • 为了处理子进程的异常退出,使用signal函数注册信号处理函数,当子进程因信号异常终止时,信号处理函数可以记录相关信息,父进程在等待子进程结束时可以检查这些信息。
  2. 异常处理
    • 信号处理函数中,通过waitpid获取子进程的退出状态,判断是否是异常退出(例如通过WIFSIGNALED宏)。如果是异常退出,记录相关信号信息。

代码实现

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>

typedef struct {
    int num_processes;
    int priority;
    pid_t *pids;
} ProcessGroup;

void signal_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));
        }
    }
}

int main() {
    // 示例数据,两组子进程
    ProcessGroup groups[] = {
        {3, 2, NULL},
        {2, 1, NULL}
    };
    int num_groups = sizeof(groups) / sizeof(groups[0]);

    // 为每组子进程分配pid数组
    for (int i = 0; i < num_groups; i++) {
        groups[i].pids = (pid_t *)malloc(groups[i].num_processes * sizeof(pid_t));
    }

    // 注册信号处理函数
    signal(SIGCHLD, signal_handler);

    // 创建子进程
    for (int i = 0; i < num_groups; i++) {
        for (int j = 0; j < groups[i].num_processes; j++) {
            pid_t pid = fork();
            if (pid == 0) {
                // 子进程任务模拟
                printf("Child %d (group %d) with priority %d is running\n", getpid(), i, groups[i].priority);
                sleep(1); // 模拟任务执行
                exit(0);
            } else if (pid > 0) {
                groups[i].pids[j] = pid;
            } else {
                perror("fork");
                exit(EXIT_FAILURE);
            }
        }
    }

    // 父进程按照优先级顺序等待子进程完成
    for (int i = 0; i < num_groups; i++) {
        for (int j = 0; j < groups[i].num_processes; j++) {
            pid_t pid = groups[i].pids[j];
            int status;
            waitpid(pid, &status, 0);
            if (WIFEXITED(status)) {
                printf("Child %d (group %d) exited normally with status %d\n", pid, i, WEXITSTATUS(status));
            }
        }
        free(groups[i].pids);
    }

    return 0;
}

代码说明

  1. 数据结构定义ProcessGroup结构体用于存储每组子进程的数量、优先级和子进程ID数组。
  2. 信号处理函数signal_handler函数用于处理子进程异常退出信号,通过waitpid获取子进程退出状态并打印异常信息。
  3. 主函数
    • 初始化ProcessGroup数组并分配内存。
    • 注册SIGCHLD信号处理函数。
    • 创建子进程并存储其ID。
    • 父进程按照优先级顺序等待每组子进程完成,并处理正常和异常退出情况。最后释放分配的内存。