【问题标题】:fork() returns 0, but the child process getpid()!=0. Why?fork() 返回 0,但子进程 getpid()!=0。为什么?
【发布时间】:2017-09-22 16:00:43
【问题描述】:

这是测试 fork() 系统调用的 C 代码:

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

int main(int argc, char *argv[])
{

    printf("I am: %d\n", (int)getpid());

    pid_t pid = fork();

    printf("fork returned: %d\n", (int)pid);

    if (pid < 0)
    {
        perror("fork failed");  
    }

    if (pid==0)
    {
        printf("I am the child with pid %d\n", (int)getpid());
        sleep(5);
        printf("Child exiting...\n");
        exit(0);
    }

    printf("I am the parent with pid %d, waiting for the child\n", (int)getpid());
    wait(NULL);
    printf("Parent ending. \n");

    return 0;
}

终端的输出是:

I am: 25110
fork returned: 25111
I am the parent with pid 25110, waiting for the child
fork returned: 0
I am the child with pid 25111
Child exiting...
Parent ending. 

问题:当fork返回:0时,是在子进程中。但是子进程显示 我是 pid 为 25111 的孩子。我以为子进程pid应该是0,为什么会变成25111呢?

和父进程一样,fork返回25111,但是getpid()返回25110(我是pid为25110的父进程,等待子进程)

【问题讨论】:

  • 您需要阅读更多内容。阅读advancedlinuxprogramming.com;我们无法在这里解释什么需要整本书来解释。请注意,fork难以理解的,所以花点时间!还要多次阅读 fork(2)fork wikipage
  • 顺便说一句,唯一的PID是0是init
  • init 是 pid 1。从字面上看(这是 POSIX 要求)没有 pid 0 这样的东西,因为 0 对于接受或返回 pid 的各种接口具有特殊含义——尤其是 @ 987654329@.
  • @R.. 我也是这么想的,尽管在我尝试过的第一台机器(一台旧的 SunOS 机器)上,ps 显示了一个名为“swapper”的 pid 0。 (但是,是的,init 是 pid 1。)
  • @SteveSummit:它是内核进程管理中的一个伪进程,但你不能使用任何带有 pid 参数的函数与它交互,因为它不是有效的 pid 号。我认为 Linux 同样有一个“pid 0”,它是空闲任务(无论如何对于 cpu0)。

标签: c process fork wait pid


【解决方案1】:

子进程显示我是 pid 为 25111 的子进程。我认为子进程 pid 应该是 0

没有。在父 fork() 返回子的 pid。在孩子中,fork 返回 0 - 这 不是 任何东西的 pid,它只是一个标记。正如getpid 告诉你的那样,子 pid 是 25111。

对于父进程,fork 返回 25111,但 getpid() 返回 25110

没错。正如getpid 告诉你的那样,父 pid 始终为 25110。并且fork()返回了新孩子的pid。

fork 在父级中返回的值与在子级中返回的getpid 相同的事实证明这一切正常。

听起来你认为 fork() 总是返回你所在进程的 pid。但这没有意义 - 我们已经有 getpid 调用它。

如果您是父进程,fork() 返回 other 进程(即子进程)的 pid。如果你是孩子,fork() 根本不会返回 pid。 (如果您是孩子并且想知道父母的 pid,这是一个很好的、常见的、单独的问题。答案:致电 getppid()。)

我们可以总结如下:

                 parent   child
                 ------   -----
pid:              25110   25111
fork returns:     25111       0
getpid returns:   25110   25111
getppid returns:  ?????   25110

记住这一点的方法是考虑将要调用fork() 的代码:它将做什么,它需要知道什么。父母需要知道它是父母。孩子需要知道这是孩子。父母经常需要知道孩子的 pid(并且没有其他方法可以获得它)。

如果fork 总是返回一个pid,那么在fork 调用之后,查看它的返回值,你将无法知道你是父母还是孩子——但这通常是第一个和您需要知道的最重要的事情。

(在所有这一切中,我忽略了第三种可能性,即fork 失败,并在父级中返回-1,并且在子级中不返回任何内容,因为没有。)

另见Why fork() return 0 in the child process?

【讨论】:

    【解决方案2】:

    fork 返回 0 并不意味着您的 pid 为 0。它只是 fork 用来告诉您您是子进程的返回值。事实上fork从不返回你的pid;它返回:

    • 您孩子的 pid,
    • 0,表示你是孩子,或者
    • -1,表示发生错误(并且没有创建子进程)

    【讨论】:

    • 再次fork 永远不会返回进程自己的 pid。它要么 (1) 告诉父级其子级的 pid,要么 (2) 使用不是任何东西的 pid 的特殊值来让您识别发生了错误或它正在新创建的子级中返回。
    猜你喜欢
    • 1970-01-01
    • 2014-11-01
    • 2021-05-04
    • 1970-01-01
    • 2017-02-14
    • 2022-01-23
    • 1970-01-01
    • 2016-08-07
    • 2015-06-21
    相关资源
    最近更新 更多