【问题标题】:Why do processes I fork get systemd as their parent?为什么我 fork 的进程将 systemd 作为其父进程?
【发布时间】:2017-03-18 08:49:26
【问题描述】:

我正在 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

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

【问题讨论】:

  • 在退出前尝试让孩子的父母wait()

标签: c linux fork systemd


【解决方案1】:

您观察到的“不一致”是因为有时父进程在其子进程终止之前退出。因此,这些子进程变为"orphans" 作为它们的 父进程不是waiting。结果,它们被“重新设置为” init 进程。 虽然传统上“init”进程的进程 ID 为 1,但并不总是如此。 POSIX 将其保留为实现定义

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

因此,您看到一个特定的 PID 作为父进程(在您的示例中为 1599),这恰好是 Linux 上等效的“init”进程。 systemd 是 Debian Linux 发行版中使用的一个 init 变体 - 它遵循稍微复杂的实现。

本质上,您观察到的情况很正常。理想情况下,您应该reap所有进程以避免zombie processes

【讨论】:

  • 谢谢!它真的对我有很大帮助:)
【解决方案2】:

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

如果您想控制您的进程以使子进程首先终止,请让父进程等待。使用wait() sys_call。

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 发行版中用于引导 用户空间并随后管理所有进程

【讨论】:

  • 术语:当一个进程在其原始父进程终止后继续运行时,通常将其称为“孤儿”,尽管这些进程被重新设置为父进程初始化过程。从这个意义上说,Linux 中肯定存在孤儿进程。它们相当普遍。
【解决方案3】:

我想,有时会发生竞争情况,父母先于孩子死去。因此,孩子从初始化过程中变成了孩子。在你的情况下,那必须是 systemd。

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

【讨论】:

  • 尝试 pstree 观察进程层次结构。
猜你喜欢
  • 2020-01-22
  • 1970-01-01
  • 1970-01-01
  • 2015-12-16
  • 2017-06-29
  • 2019-10-17
  • 2023-03-15
  • 2017-12-09
  • 2017-06-27
相关资源
最近更新 更多