当 parent 进程不是 root 时,有什么方法可以确定 child 进程被内核用 SIGKILL 杀死

Is there any way to figure out that child process was killed with SIGKILL by the kernel when the parent process isn't root

我的情况是有一个非根用户(所以我无法读取内核日志)parent 进程及其 child,child 可能已被 SIGKILL 杀死内核消耗大量内存。当它发生时 parent 进程应该知道 child 由于超出内存限制(理想情况下)而被杀死,但我什至不知道我是否可以弄清楚它被杀死了SIGKILL,更不用说原因了。所以我需要从 parent 进程的一侧了解 child 是否被 SIGKILL 杀死,以及是否是它发生的原因(但这是第二个问题)。

有人可以给我建议吗?谢谢。

您需要在 child 上 wait(2) 并使用宏 WIFSIGNALED 检查它是否被信号终止。

int status = 0;

// wait for child to exit
pid_t child_pid = wait(&status);

if (WIFEXITED(status))
{
    printf("exited with %d\n", WEXITSTATUS(status));
}
else if (WIFSIGNALED(status))
{
    printf("Signaled with %d\n", WTERMSIG(status));
}

如果你有多个 child 进程,你可以使用一个循环来等待它们。

WTERMSIG(status) 将 return 信号编号。要找出信号,您可以检查:

if (WTERMSIG(status) == SIGKILL) {
    ...
} else if (WTERMSIG(status) == SIGTERM) {
    ...
}

无法确定到底是谁发出了杀戮(无论是 OOM 杀手还是其他东西,例如,可以从 shell 中 kill -9 PID)。 可以合理地假设信号不会在系统上不分青红皂白地发送,并且通常是内核本身(OOM 杀手)发送 SIGKILL.

waitXXX( )(see man page) 提供的状态可以确定 child 已被信号杀死: 首先通过调用 WIFSIGNALED(wstatus) 来检查是否发生了,然后您可以调用 WTERMSIG(wstatus) 来确定信号编号。但是,您无法确定该进程是被内核终止还是被另一个调用 kill().

的进程终止