3

Can someone please explain to me what does fork() != 0 mean? From what I understand I think it means if fork is not false? Or if fork is true then.... I don't understand how Fork() can be true or false, seeing that it just creates a copy of a process into a parent and child. Also if a program where to say if (Fork() == 0) what would that mean?

 #include "csapp.h"

 int main(void)
 {
     int x = 3;

     if (Fork() != 0)
         printf("x=%d\n", ++x);

     printf("x=%d\n", --x);
     exit(0);
 }
Jens
  • 69,818
  • 15
  • 125
  • 179
user12074577
  • 1,371
  • 8
  • 25
  • 30
  • did you read up some documentation about `fork`? googling for it brings up plenty of explanations how it works, and how you'd use the return value from it. – Jens Gustedt Sep 14 '12 at 21:23
  • 1
    It's very bad practice to call `exit` in both the parent and the child. If, for example, the process had buffered file output prior to calling `Fork`, both the parent and the child will flush that output when they call `exit`. – David Schwartz Apr 16 '13 at 01:59

6 Answers6

6

fork() returns -1 if it fails, and if it succeeds, it returns the forked child's pid in the parent, and 0 in the child. So if (fork() != 0) tests whether it's the parent process.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
3

From man fork

Return Value

On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately.

Assuming success, fork returns twice: once in the parent, and once in the child.


OK, I did the OP a disservice: I don't know where csapp.h comes from, but if it's this one then it isn't doing you any favours. I guess it is a thin wrapper on POSIX (eg. around fork()), but maybe works on other platforms too?

Because you mentioned fork() before Fork(), I assumed the latter was a typo, whereas it's actually a library function.

If you had been using fork() directly, it would be reasonable to expect you to check the manpage. Since you're using a Fork() function provided by some library, that library really ought to document it, and doesn't seem to.


Standard (non csapp) usage is:

pid_t child = fork();
if (child == -1) {
    printf("fork failed - %d - %s\n", errno, strerror(errno));
    exit(-1);
}
if (child) {
    printf("I have a child with pid %d, so I must be the parent!\n", child);
} else {
    printf("I don't have a child ... so I must be the child!\n")
}
exit(0);
Useless
  • 64,155
  • 6
  • 88
  • 132
  • if it is successful, and returns in two (otherwise identical) processes ... what is the return value in each? – Useless Sep 14 '12 at 19:14
  • when fork returns, you have two processes running in parallel, each with their own copy of `x` ... for example, `child` is a single variable in my sample code above, but each process gets a seperate copy with a different value – Useless Sep 14 '12 at 19:23
  • 1
    csapp.h comes from a textbook, and the documentation of the wrapper is in the book itself: http://www.amazon.com/Computer-Systems-Programmers-Perspective-Edition/dp/0136108040. – Adam Mihalcin Sep 14 '12 at 20:22
3

Let's try explaining it differently... When the function starts there's 1 process, this process has a int x = 3

Once you hit this line of code:

if (fork() != 0)

Now, assuming the fork() worked, we have two processes. They both have the same execution space, they both are going to run the same code (to a point), but the child will get its own copy of x to play with.

fork() will return a 0 to the child process, so from the child processes' prospective, the rest of the function is this:

printf(("x=%d\n", --x);
exit(0);

The parent process on the other hand, will get a valid value back from the fork() command, thus it will execute:

printf("x=%d\n", ++x);
printf("x=%d\n", --x);
exit(0);

What the output at this point will be is anyone's guess... You can't tell if parent or child will run first

But if we assume the parent hits the ++x is the next operation then the output is:

x=4
x=3
x=2

As both parent and child will hit the --x. (the parent's x was 4 after the ++x, will be 3 at the end. The child's x was 3, will be 2 at the end)

Community
  • 1
  • 1
Mike
  • 47,263
  • 29
  • 113
  • 177
2

From fork() manual:

Upon successful completion, fork() returns a value of 0 to the child process and returns the process ID of the child process to the parent
     process.  Otherwise, a value of -1 is returned to the parent process, no child process is created, and the global variable errno is set to indi-
     cate the error.

After the code execution you have two execution threads. Into the if statement you have the parent process' thread and in else statement you have the child process' thread.

if ( fork() ) { 
    printf("I am the parent!\n"); 
} else {
    printf("I am the child\n");
}

EDIT

For clarification purpose: fork starts a process, which has a thread, memory and may have other resources. I tried (it seems like that without success) to emphasize the flows of execution by adding the "thread" word. However, by no means, one can say that "parent" relates to "thread" in "parent process' thread".

Of course, my answer could be improved but I think there are already enough good answers here.

olivecoder
  • 2,858
  • 23
  • 22
  • Sorry @Useless but I didn't say they are not processes: "parent process' thread" means the (main/only) thread of execution on each process. It may have misled you but I was trying to emphasize the two flows of execution. – olivecoder Mar 10 '17 at 07:35
  • I repeated the process word changing "child's thread" to "child process' thread" to improve that. Thanks @Useless. – olivecoder Mar 10 '17 at 07:58
1

Fork returns 0 for the child process and the process id of the child to the parent process. Hence commonly code has if(fork){ }else code. Which implies that the code inside the if is going to be executed only in a parent.

The better way to deal with it is

 pid = fork()
 if(pid){
  // I am parent. Let us do something that only the parent has to do
 }else{
 // I am child. Let us do something only the child has to do
 }
 // This code is common to both

The child pid may be useful to wait upon later or to detach from the parent.

av501
  • 6,645
  • 2
  • 23
  • 34
1

I recommend replacing the if with a switch because there are 3 possible results:

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

pid_t pid;

switch ((pid = fork ())) {
case -1: /* error creating child. */
  break;
case 0:  /* I am the child process. */
  break;
default: /* I am the parent process. */
  break;
}
Jens
  • 69,818
  • 15
  • 125
  • 179