为什么我fork的进程会有systemd作为它们的父进程?

6

我正在学习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 }

有时候它运行正常,结果如下:
./test1.out
parent pid:27596 ppid:21425
pid:27599 ppid:27597
pid:27597 ppid:27596
pid:27598 ppid:27597
pid:27600 ppid:27598

但结果并不一致,更经常的是它像这样工作:

parent pid:27566 ppid:21425
pid:27567 ppid:27566
pid:27568 ppid:27567
pid:27569 ppid:1599
pid:27570 ppid:1599

这个对我来说毫无意义,因此我输入了$ps aux命令以查找进程1599是什么(删除了一些列)。

  USER       PID  VSZ   RSS    STAT START   COMMAND
  linux     1599  63236  6316   Ss   09:03  /lib/systemd/systemd --user

有人能帮我整理一下吗?

这句话与IT技术无关。

2
尝试在退出之前让父进程等待子进程。 - Klas Lindbäck
3个回答

7
你观察到的“不一致性”是因为有时候,父进程在其子进程终止之前已经退出。因此,这些子进程成为"孤儿",因为它们的父进程没有等待它们。结果,它们被“重新分配”给init进程。虽然传统上“init”进程的进程ID为1,但这并不总是正确的。POSIX将其留给实现定义

调用进程所有现有子进程和僵尸进程的父进程ID都应设置为一个特定系统进程的进程ID,这些进程将由特殊系统进程继承。

因此,您可以在您的示例中将特定PID(1599)视为父进程,这恰好是Linux上的“init”进程等效物。systemd是Debian Linux发行版中使用的一种init变体,其实现稍微复杂一些。
本质上,您观察到的是非常正常的。理想情况下,您应该收割所有进程,以避免僵尸进程

谢谢!这真的帮了我很多 :) - Lucas

4
我想有时候会发生竞态条件,父进程在子进程之前死亡。因此,子进程将成为来自 init 进程的孤儿进程。在您的情况下,这必须是 systemd。
无论如何,请注意运行 fork(); fork(); 会产生四个进程,这可能不是您想要的。使用控制结构,就像您在第一个结构中所做的那样,以对程序的行为进行精细控制。

2
尝试使用pstree观察进程层次结构。 - Aif

2

这是因为父进程先终止了。 在Linux中没有孤儿进程。它们被分配给init进程。

如果您想控制进程,使子进程先终止,请让父进程等待。使用wait()系统调用。

Example:

   #include <stdio.h>
   #include <stdlib.h>
   #include <unistd.h>
   int main(void)
   {
        int pid;
        int pid2;
        pid = fork();
        if(pid < 0){
                 exit(1);
        }
        if(pid == 0){ // child process
            pid2 = fork()
            if (pid2 < 0)
                exit(1);
            if (pid2 == 0)
            {
                printf("pid:%dppid:%d\n",getpid(),getppid());
                exit(0);
            }
            wait();
            printf("pid:%d ppid:%d\n",getpid(),getppid());
            exit(0);
        }
        else{         // parent process
           wait();
           printf("parent pid:%d ppid:%d\n",getpid(),getppid());
           exit(0);
        }       
        return 0;            
  }

systemd是Linux发行版中使用的初始化系统,用于引导用户空间并随后管理所有进程


4
术语:当一个进程在其原始父进程终止后仍然运行时,惯例上将该进程称为“孤儿”,尽管这些进程已被重新分配给 init 进程。从这个意义上说,在 Linux 中肯定有孤儿进程;它们相当普遍。 - John Bollinger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接