为什么Linux中的孤儿进程没有被PID 1收养,就像我读过的书上所说的那样?

问题描述 投票:0回答:1

我在读《Linux 编程接口》一书,看到这句话(在第 6.2 章末尾):

如果子进程因其“出生”父进程终止而成为孤儿进程,则该子进程将被 init 进程采用,并且子进程中对 getppid() 的后续调用将返回 1。

所以我写了一些代码来查看这一点。这是代码:

#include <unistd.h>
#include <stdio.h>

int main()
{
    printf("starting...\n");

    if (fork() == 0)
    {
        printf("Child PID: %d\n",getpid());
        printf("Child PPID: %d\n",getppid());
        printf("sleeping till the parent die:(\n");
        sleep(5);
        printf("Child new PPID: %d\n",getppid());
    }
    else
    {
        printf("Parent PID: %d\n",getpid());
    }

    return 0;
}

运行代码后,我得到以下输出:

starting...
Parent PID: 16577
Child PID: 16578
Child PPID: 16577
sleeping till the parent die:(

Child new PPID: 2754

不仅

getppid()
不返回1,看起来PID 1甚至不是
init
进程,而是一个
systemd
进程。其中有多个:当我运行
pgrep systemd
时,它会输出 1 和 2754 等。

现在我很困惑,这些是我的问题:

  • init
    流程在哪里?
  • 为什么会有多个
    systemd
    进程?
c process operating-system systemd
1个回答
0
投票

看起来PID 1甚至不是init进程,而是一个systemd进程

systemd 进程init 进程。它与传统 init 不是同一个软件,但它仍然执行 init 通常执行的所有功能(甚至更多;它不仅仅是 init 的直接重新实现)。

虽然“SysV init”历来是 Linux 上最流行的 init,但它从来都不是唯一的 – 它是一个发行版选择,所以你还有 init-ng、s6、Upstart、systemd 等。

其中有多个:当我运行 pgrep systemd 时,它输出 1 和 2754 等。

服务管理并不只限于 init/pid1——尽管 pid1 由于是默认父级而具有一定的优势——但有一个“用户级”服务管理器做大致相同的事情是相当常见的。例如,当您登录 GNOME 时,第一个进程是 gnome-session – 它只是另一种服务管理器,除了开始监督各种其他 GNOME 组件之外什么也不做。

因此,systemd 自然支持一种模式,可以作为普通的非 pid1 进程运行并为一个特定用户管理服务(通过

systemctl --user
)。如今,您的大部分 GUI 环境组件都是通过这种方式启动的。

(你并没有真正在 SysV 风格的 init 中看到它,因为它的服务管理功能......缺乏,几乎所有事情都是通过 shell 工具outside init 正确完成的。但是 Upstart 和 systemd 都直接在 pid1 内处理服务。)

因此,

getppid() 不仅不返回 1

正如评论中所指出的,Linux 现在为独立服务管理器提供了一个 API,使其成为其子进程的新默认父进程(收割者)。 Systemd 在其“每用户”模式下使用此功能是为了更轻松地处理尝试“守护进程”(并因此成为孤立的)的服务。

© www.soinside.com 2019 - 2024. All rights reserved.