You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用waitpid的父进程如何识别终止子进程的信号发送进程?

如何确定发送终止信号给子进程的进程ID?

waitpid() 及其配套的宏(WIFSIGNALED、WTERMSIG等)只能告诉你子进程是被信号终止的,以及具体是哪个信号,但无法直接提供发送该信号的进程ID。要获取这个信息,你可以根据场景选择以下几种方法:

方法1:利用Linux审计机制(无需修改代码)

Linux的audit子系统可以监控系统内的信号发送事件,适合无法修改子进程代码的场景:

  1. 先确保auditd服务已启动:systemctl start auditd
  2. 添加监控kill系统调用的规则:
    auditctl -a exit,always -F arch=b64 -S kill
    
    (如果是32位系统,把b64换成b32)
  3. 当子进程被信号终止后,用ausearch查询审计日志:
    ausearch -i -sc kill
    
    日志里会包含sender_pid(发送信号的进程ID)和target_pid(被信号终止的进程ID),你可以通过target_pid匹配你的子进程,从而找到对应的sender_pid。

方法2:通过ptrace跟踪子进程(父进程主动监控)

父进程可以用ptrace跟踪子进程,在子进程收到信号时获取信号的详细信息,包括发送者PID:

  1. 子进程启动时调用ptrace(PTRACE_TRACEME, 0, NULL, NULL),让父进程可以跟踪自己;
  2. 父进程调用waitpid()等待子进程状态变化,当子进程因信号停止时(WIFSTOPPED(status)为真),调用ptrace(PTRACE_GETSIGINFO, pid, NULL, &info)获取信号信息;
  3. siginfo_t结构体中的si_pid字段就是发送信号的进程ID。

简单代码示例:

#include <sys/ptrace.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>

int main() {
    pid_t pid = fork();
    if (pid == 0) {
        // 子进程:允许父进程跟踪
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        // 执行子进程逻辑,比如sleep等待信号
        sleep(60);
        return 0;
    } else {
        int status;
        siginfo_t info;
        while (waitpid(pid, &status, 0) > 0) {
            if (WIFEXITED(status)) {
                printf("子进程正常退出,退出码:%d\n", WEXITSTATUS(status));
                break;
            } else if (WIFSIGNALED(status)) {
                printf("子进程被信号终止,信号:%d\n", WTERMSIG(status));
                break;
            } else if (WIFSTOPPED(status)) {
                int sig = WSTOPSIG(status);
                // 获取信号的详细信息,包括发送者PID
                if (ptrace(PTRACE_GETSIGINFO, pid, NULL, &info) == 0) {
                    printf("子进程收到信号%d,发送者PID:%d\n", sig, info.si_pid);
                }
                // 让子进程继续运行(如果不需要暂停)
                ptrace(PTRACE_CONT, pid, NULL, NULL);
            }
        }
    }
    return 0;
}

注意:ptrace会对子进程的运行性能有轻微影响,且需要父进程有足够权限。

方法3:子进程自定义信号处理(仅适用于可控子进程)

如果子进程是你自己编写的,可以在子进程中捕获可处理的信号,获取发送者PID后通知父进程:

  1. 在子进程中安装带siginfo_t参数的信号处理函数(用sigaction,设置SA_SIGINFO标志);
  2. 当收到信号时,从siginfo_t的si_pid拿到发送者PID,通过管道、套接字等IPC方式发送给父进程;
  3. 父进程读取到信息后,就知道是哪个进程发的信号。

局限性:这种方法无法处理不可捕获/忽略的信号(比如SIGKILL、SIGSTOP),因为这些信号的处理函数无法被触发。


内容的提问来源于stack exchange,提问作者yqq hqq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 04:30:06