Starting a process with the fork() call

Suppose you want to create a new process that's identical to the currently running process and have it run concurrently. You could approach this with a spawn() (and the P_NOWAIT parameter), giving the newly created process enough information about the exact state of your process so it could set itself up. However, this can be extremely complicated; describing the “current state” of the process can involve lots of data.

There is an easier way—the fork() function, which duplicates the current process. All the code is the same, and the data is the same as the creating (or parent) process's data.

Of course, it's impossible to create a process that's identical in every way to the parent process. Why? The most obvious difference between these two processes is going to be the process ID—we can't create two processes with the same process ID. If you look at fork()'s documentation in the QNX Neutrino C Library Reference, you'll see that there is a list of differences between the two processes. You should read this list to be sure that you know these differences if you plan to use fork().

If both sides of a fork() look alike, how do you tell them apart? When you call fork(), you create another process executing the same code at the same location (i.e., both are about to return from the fork() call) as the parent process. Let's look at some sample code:

int main (int argc, char **argv)
{
    int retval;

    printf ("This is most definitely the parent process\n");
    fflush (stdout);
    retval = fork ();
    printf ("Which process printed this?\n");

    return (EXIT_SUCCESS);
}

After the fork() call, both processes are going to execute the second printf() call! If you run this program, it prints something like this:

This is most definitely the parent process
Which process printed this?
Which process printed this?

Both processes print the second line.

The only way to tell the two processes apart is the fork() return value in retval. In the newly created child process, retval is zero; in the parent process, retval is the child's process ID.

Clear as mud? Here's another code snippet to clarify:

printf ("The parent is pid %d\n", getpid ());
fflush (stdout);

if (child_pid = fork ()) {
    printf ("This is the parent, child pid is %d\n",
            child_pid);
} else {
    printf ("This is the child, pid is %d\n",
            getpid ());
}

This program will print something like:

The parent is pid 4496
This is the parent, child pid is 8197
This is the child, pid is 8197

You can tell which process you are (the parent or the child) after the fork() by looking at fork()'s return value.