moomin
moomin

Reputation: 49

Why is this global counter not decrementing in the child process?

In this snippet, (ignoring all the printfs besides second last), I expect the counter to be at 1 by the end.

int counter = 1; //GLOBAL!

int main() 
{
    if (fork() == 0) {
        printf("child has spoken!\n");
        counter--; 
        printf("and counter is now: %d\n", counter);    
        exit(0);
    }
    else {
        printf("what is counter here?: %d\n", counter);
        printf("now we'll wait\n");
        wait(NULL);
        printf("we've waited long enough!\n");
        printf("counter = %d\n", ++counter);
        printf("counter is 2????: %d\n", counter);
    }
    exit(0);
}

The process can be seen in what is printed to output.

what is counter here?: 1
now we'll wait
child has spoken!
and counter is now: 0
we've waited long enough!
counter = 2
counter is 2????: 2

The else is entered first, counter is still at 1, we wait(NULL) for the child to die. Back up in the if, fork() creates the child, but seeing as fork() == 0, only the child decrements the counter by 1. Now the counter is 0, and the child terminates at exit(0). The wait is over, child is dead, and parent prints ++counter which should be 0 + 1 = 1, but suddenly it's 2, not 1! Why is this so?

Upvotes: 1

Views: 140

Answers (1)

Tom Karzes
Tom Karzes

Reputation: 24052

From the Linux man page for fork:

Under Linux, fork() is implemented using copy-on-write pages, so the only penalty that it incurs is the time and memory required to duplicate the parent's page tables, and to create a unique task structure for the child.

This means that any time you write to memory in either the parent or child process, the page being written is copied and the two processes end up with independent copies.

Upvotes: 2

Related Questions