tags:

views:

461

answers:

6

I'm really new to C programming, although I have done quite a bit of other types of programming.

I was wondering if someone could explain to me why this program outputs 10.

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

int value = 10;

int main()
{
    pid_t pid;

    pid = fork();
    if(pid == 0){
    value += 10;
    }
    else if(pid > 0){
        wait(NULL);
        printf("parent: value = %d\n", value); //Line A
        exit(0);
    }
}

I know the output is "parent: value = 10". Anyone know why?

Thanks!

+16  A: 

fork creates two processes (the "parent" and the "child"). Each process has a different value of pid in your example. The child process has a pid of 0. The parent process has a pid of the child's operating system pid (assigned by the OS.)

In your example, each process has it's own value in its memory. They do not share memory (like you think they should by your question.) If you change one process (the first part of the if) it will not be reflected in the second process (the second part of the if.)

Edit: Explained the value of pid.

Starkey
the pid returned by fork is 0 for child process and greater than 0 for parent process.
Cătălin Pitiș
why is the PID for the child proccess 0? Why would the parent proccess not be 0 and each child increment from there?
kralco626
@kralco626: `man fork` says: "On success, the PID of the child process is returned in the parent, and 0 is returned in the child."
Bruno
@kralco: So that it is easy to identify which process "you" are. Any process can easily get it's own PID or it's parent's by asking the OS (`getpid` and `getppid` in unix).
dmckee
@kralco626: That's just how `fork()` works. That way, the parent process will know the exact pid of its child (> 0), and the child will know it's the child process (because pid will return 0). Note that the child doesn't *actually* have a process ID of 0, it's just `fork()`'s way of signaling to the child that it is, in fact, a child process. (It's also trivial for a child process to get the PID of itself as well as its parent, since it only has one parent, whereas a parent may have multiple child processes).
mipadi
Small correction: fork() does not create 2 processes. It creates one new process which is a copy of the original process ... in *almost* every way.
Lee-Man
A: 

fork() creates a new process: it has two return values in two different contexts, so both paths run in your if statement. The conditional is mostly used to determine which process you run in after the fork.

Jurily
but there is only one output line. Can you walk me through whats going on? Why does the parent AND the child process not create and output statement?
kralco626
Because in the child, fork returns 0. In the parent, fork returns the pid of the child.
Jurily
haha ya now I get it. The proccess splits from the point of the fork() call. The child proccess with a value of 0 and the parent with a value grater than 0. I think I get it!
kralco626
+2  A: 

Well, fork spawns a new process. It more or less copies the current process, and both the new one (the child) and the old one (the parent) go on at the same point in the code. But there is one significant difference (that interests us) here: for the child, fork returns 0. For the parent, it returns the process ID of the child.

So the if(pid ==0) part is true for the child. The child simple add 10 to his value, and then exits since there is no further code.

The else part is true for the parent (except for the very rare case that fork returned an error with -1). The parent simply waits for the child to exit. But the child has modified its own copy of value, the one of the parent is still untouched and that is why you get the output of "10". Then the parent also exits.

DarkDust
+4  A: 

About fork() :

  • If fork() returns a negative value, the creation of a child process was unsuccessful.
  • If fork() returns a zero to the newly created child process.
  • If fork() returns a positive value, the process ID of the child process, to the parent.

So in you case it bound to return a number greater than 0 & thus the value will remain 10 & will be printed.

loxxy
Awesome answer. I'm trying to wrap my head around this. So the parent proccess gets a number greater than 0 and therefore going into the else part and print. The child proccess gets a 0. What does this child proccess do? Does it create a new proccess that executes from the current line? or from the beginning of the code?
kralco626
@kralco626 it's a copy of the parent process, executing from the same point/state: http://man.cx/fork%282%29
Bruno
A: 

when you call fork, it creates a copy of the process in such a way that both the copies' program counters are at the same position in their code sections. Hence when any of these copies resumes execution, both will just be finishing the call to fork.

So both of them should execute identically.

BUT, fork returns 0 in the child process, and the pid of the child process in the parent process.

That explains the mojo behind the if( pid==0 ) part.

So when the child process changes the value of value, it actually changes that in its own copy (remember: the process got copied, so the data sections got copied too).

Meanwhile, the parent process executes with its old value of value, which is 10.

Even after the child changes its copy of value and dies, the parent's copy is still 10.

Here Be Wolves
A: 

The fork system call creates a new process as a child of the existing (parent) process. Both the parent and the child continue execution at the line following the fork statement, however the child process is given an exact copy of the parents address space.

The fork system call returns the process id of the newly created process to the parent and zero to the child, therefore within this code the child will increment its own copy of the value variable and the parent will print out its own copy.

You will often see fork followed by an exec within the child so that it replaces itself with another program.

Steve Weet