How to use fork() in an if statement

2019-05-23 13:15发布

问题:

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

回答1:

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.



回答2:

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);


回答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)



回答4:

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.



回答5:

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.



回答6:

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


标签: c fork