【问题标题】:Why does my forked process's parent pid differ from the parent's own pid?为什么我的分叉进程的父 pid 与父进程自己的 pid 不同?
【发布时间】:2018-07-02 02:26:50
【问题描述】:

我试图了解一些unistd.h 函数的工作原理。 这是我写的代码:

#include <stdlib.h>
#include <unistd.h>

int main(){
  pid_t pid;
  pid=fork();
  switch(pid) {
  case 0: //child
     printf("case 0:\nchild %d\nparent %d\n", getpid(), getppid());
     break;
  default: //parent
     printf("default:\npid(child) %d\nparent %d\n", pid, getpid());
     break;
  }
}

我觉得case 0getppid()得到的父pid和default情况下getpid()得到的父pid应该是一样的,但是这是我的小程序的输出:

default:
pid(child) 29208
parent 29207

Process returned 0 (0x0)   execution time : 0.001s
Press ENTER to continue.
case 0:
child 29208
parent 1017

为什么它们不同? (一个是 29207,另一个是 1017)

【问题讨论】:

  • 我猜这可能是由于终端中的 shell 同步不正确。您可以让孩子和父母将他们的输出写入单独的文件并进行比较吗?
  • 您可能应该在父项中wait() 让子项完成。

标签: c fork pid unistd.h


【解决方案1】:

您应该减慢执行速度。正如您在您的终端中看到的,孩子在父母完成后被执行。在这种情况下,它变成了一个孤儿,并且它的 PID 被重新分配给不同的进程。我不知道这在 Linux 上是否同样有效,但在我的 Mac 上它被重新分配给进程 1。所以在 每个 父级的 printf() 之前添加 sleep()

编辑

我已经编译(使用llvm-gcc 编译)并在添加睡眠之前运行您的代码:

 $  ./test
default:
pid(child) 2688
parent 2687
case 0:
child 2688
parent 1

然后:

 $  ./test 
default:
pid(child) 2780
parent 2779
case 0:
child 2780
parent 2779

EDIT2

由于将sleep() 放入孩子的 PID 并不能解决任何问题,因此我更改了关于应放置在何处的建议。

EDIT3

由于接受的是我的回答而不是 Toby 的回答,后者更好,值得一提的是,适当的同步机制将利用 wait() 函数。

【讨论】:

  • 据我了解,孤儿进程由init 继承,它不会有 id 1017。sleep 可能已经解决了这个问题。但出于不同的原因。
  • @AjayBrahmakshatriya 这就是我在课堂上被告知的内容。我不知道它在 Linux 上的工作原理(而且我手头没有任何 VM 可以快速测试它)。我已经添加了一些我在执行期间得到的比较。
  • @gonczor 我在 Linux 上检查了它,如果我在孩子中放置 sleep() 一秒钟,我会得到 1 作为 PPID。除此之外,您将sleep() 放在两个 printf 之前的解决方案什么也解决不了。也许您可以建议仅在父母中添加睡眠。所以它肯定会在孩子终止后终止。
  • @AjayBrahmakshatriya 我的教授说,最近的操作系统进程可能不是 PID1 (init) 而是自定义的 init 用户,所以我认为这就是它具有 PID 1017 的原因
  • 在最近的一些 Linux 上,一个进程可以被指定为其(直接和间接)后代的采用者。这是为了支持容器而实现的(容器的 init 进程不一定是主机命名空间中的 PID 1)。也许您的平台上存在类似的东西?
【解决方案2】:

如果父母没有为孩子wait(),它可能会在孩子调用getppid()之前退出。如果您希望父母仍然存在并成为父母,您可以通过使其等待来确保这一点:

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
    const pid_t pid = fork();
    switch (pid) {
    case 0:
        printf("in child: me: %d; parent %d\n", getpid(), getppid());
        break;
    default: //parent
        printf("in parent: child: %d; me %d\n", pid, getpid());
        wait(NULL);
        break;
    }
}

(为方便起见,我还添加了您忘记包含的标题 - 这表明您没有在编译中启用足够的警告)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-12
    • 2010-09-05
    • 2021-06-24
    • 2015-12-23
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    相关资源
    最近更新 更多