Search code examples
cprocessforkwaitpid

fork() returns 0, but the child process getpid()!=0. Why?


This is the C code to test fork() system call:

#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;
}

The output in terminal is:

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. 

Question: When fork returned: 0, it is in the child process. But the child process shows I am the child with pid 25111. I thought the child process pid should be 0, why it changes to 25111?

Same thing with the parent process, fork returned 25111, but getpid() returns 25110 (I am the parent with pid 25110, waiting for the child)


Solution

  • the child process shows I am the child with pid 25111. I thought the child process pid should be 0

    No. In the parent fork() returns the pid of the child. In the child, fork returns 0 -- which is not the pid of anything, it's just a marker. The child pid is 25111, as getpid told you.

    with the parent process, fork returned 25111, but getpid() returns 25110

    Right. The parent pid was always 25110, as getpid told you. And fork() returned the pid of the new child.

    The fact that fork returned the same value in the parent as getpid returned in the child proves that this is all working properly.

    It sounds like you think fork() always returns the pid of the process that you're in. But that wouldn't make sense -- we already have the getpid call for that.

    If you're the parent, fork() returns the pid of the other process, the child. And if you're the child, fork() doesn't return a pid at all. (If you're the child and you want to know the pid of your parent, that's a good, frequent, and separate question. Answer: call getppid().)

    We can summarize all this as follows:

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

    The way to remember this is to think about the code that's going to be calling fork(): what it's going to do, what it needs to know. The parent needs to know that it is the parent. The child needs to know that it is the child. The parent very often needs to know the pid of the child (and would have no other way of obtaining it).

    If fork always returned a pid, then after the fork call, looking at its return value, you would have no way of knowing whether you were the parent or the child -- but this is typically the first and most important thing you need to know.

    (In all of this I've ignored the third possibility, namely that fork fails, and returns -1 in the parent, and doesn't return anything in the child, because there isn't one.)

    See also Why fork() return 0 in the child process? .