views:

528

answers:

5

Im not understanding the output of this program:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

int i = 0;

int main()
{
    while(i<3)
    {
        fork();

        printf("%d\n",i);
        ++i;
    }
}

The output is: 0 1 2 2 1 2 0 1 2 2 2 1 2 2

Can please someone tell me how i should tackle this issue in order to fully understand why im having this output??

Thanks a lot. Cheers ;)

+14  A: 

Fork will make a copy of the process. An independent copy of the process. So, if a global variable contains 3 at the time you fork, each copy of the process gets their very own 3. And if they modify, their modifications are completely independent.

bmargulies
+1  A: 

Try using pthreads if you want to create a thread inside the process for concurrent programming. The function you want is pthread_create and pthread_join for tidying up later.

Something like this:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <malloc.h>


int i = 0;

void *threadFunc(void *arg) 
{
    printf("%d\n",i);
}

int main()
{
    int j = 0;  
    int returnValue = 0;
    pthread_t* myThread = (pthread_t*) calloc(3, sizeof(pthread_t));;

    while(i < 3)
    {

        returnValue = pthread_create(&myThread[i], NULL, threadFunc, NULL);
        printf("main thread: %d\n",i);
        i++;

    }


    for(j = 0; j < 3; j++)
    {
        pthread_join(myThread[j], NULL); 

    }

    return 0;
}

But perhaps not, depending on your actual needs.

Ninefingers
+3  A: 

When you fork(), a complete copy of the current process is created in its current state. This means that your initial process will create three new processes that are in the middle of the while loop, with i being respectively 0, 1, and 2 in each one of them. It will also print his own values of i.

Each of its children will continue the loop from the fork() call by printing out its initial i value, incrementing and looping. This means that children 0 will print 0, 1, and 2, and spawn two new children, with "initial" values of i 1 and 2. Children 1 will print 1 and 2 and spawn one more children, with an "initial" value of i of 2. Children 2 will print 2 and leave the loop.

If you continue this reasoning you will come to the conclusion that in total two 0's, four 1's and eight 2's will be printed. But, since the order of execution depends on how the OS schedules the concurrent processes, you cannot have guarantees on the order those are printed.

Martinho Fernandes
+9  A: 

Change your code to this and the output should make a lot more sense:

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

int i = 0;

int main()
{
    while (i < 3)
    {
        fork();
        printf("pid = %d, i = %d\n", getpid(), i);
        ++i;
    }
    return 0;
}
Paul R
A: 

It's something like...

 1 (main) instance, i = 0(unforked)
 fork() > 2 instances, with i's = 0(forked), and 0(forked)
0 output from main instance, increments its i, 2 instances with i = 1u, 0f
 main instance forks, there's 3 instances with i's 1f, 1f, 0f
1 output from main instance, increments its i, 3 instances with i = 2u, 1f, 0f
 main instance forks, there's 4 instances with i's 2f, 2f, 1f, 0f
2 output from main instance, increments its i, 4 instances with i = 3u, 2f, 1f, 0f
 main instance then dies, 3 instances with i = 2f, 1f, 0f
2 output from next instance, increments its i, 3 instances with i = 3u, 1f, 0f
 next instance then dies, 2 instances with i = 1f, 0f
1 output from next instance, increments its i to 2, 2 instances with i = 2u, 0f

...etc

The order that the processes are outputting in, however, is undetermined, so you likely won't see the exact same output every time, and even if you do it's not something you can guarantee.

As other people said, each process has its own global 'i' that it keeps track of, and its value is simply the value of the forking process's i at the fork.

Tanzelax