为什么我派生的进程将systemd作为其父级?

Luc*_*cas 5 c linux fork systemd

我正在Linux中学习fork(),这是我的程序:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 int main(void){
  5         int pid;
  6         pid = fork();
  7         if(pid < 0){
  8                 exit(1);
  9         }
 10         if(pid == 0){
 11                 fork();
 12                 fork();
 13                 printf("pid:%d ppid:%d\n",getpid(),getppid());
 14                 exit(0);
 15                 }
 16         else{
 17                 printf("parent pid:%d ppid:%d\n",getpid(),getppid());
 18                 exit(0);
 19         }       
 20        
 21 }
Run Code Online (Sandbox Code Playgroud)

有时效果很好,结果如下:

./test1.out
parent pid:27596 ppid:21425
pid:27599 ppid:27597
pid:27597 ppid:27596
pid:27598 ppid:27597
pid:27600 ppid:27598
Run Code Online (Sandbox Code Playgroud)

但是结果并不一致,通常是这样的:

parent pid:27566 ppid:21425
pid:27567 ppid:27566
pid:27568 ppid:27567
pid:27569 ppid:1599
pid:27570 ppid:1599
Run Code Online (Sandbox Code Playgroud)

这对我来说没有任何意义,所以我输入了$ ps aux以找出1599的处理过程:(删除了一些列)

  USER       PID  VSZ   RSS    STAT START   COMMAND
  linux     1599  63236  6316   Ss   09:03  /lib/systemd/systemd --user
Run Code Online (Sandbox Code Playgroud)

有人可以帮我整理一下吗?

P.P*_*.P. 5

您观察到的“不一致”是因为有时父进程其子进程终止之前就退出了。因此,这些子进程成为“孤儿”,因为其父进程不在等待它们。结果,它们被“重新父”到了初始化过程。传统上,“ init”进程的进程ID为1,但并不总是如此。POSIX将其保留实现定义的内容

调用进程的所有现有子进程和僵尸进程的父进程ID必须设置为实现定义的系统进程的进程ID。即,这些过程应由特殊的系统过程继承。

因此,您会看到一个特定的PID作为父对象(在您的示例中为1599),在您的Linux上恰好相当于“初始化”进程。该systemd是Debian的Linux发行版使用的初始化变种-它遵循一个稍微复杂的实现。

本质上,您观察到的是很正常的。理想情况下,您应该收获所有进程以避免僵尸进程


Aif*_*Aif 4

我想,有时,会发生竞争条件,父母先于孩子去世。因此,子进程成为 init 进程的子进程。就你而言,这必须是 systemd。

无论如何,请注意,运行fork(); fork();将产生 4 个进程,这(可能)不是您想要的。像使用第一个结构一样使用控制结构来对程序的行为进行精细控制。

  • 尝试使用 pstree 来观察进程层次结构。 (2认同)