8

I'm 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 I'm getting this output?

Paul R
  • 208,748
  • 37
  • 389
  • 560
Bruno
  • 217
  • 1
  • 2
  • 5
  • 2
    You haven't told us what you don't like about this. – bmargulies Jan 28 '10 at 22:15
  • I dont like because i dont understand when we are incrementig the fork on the parent process or in the children's processes. Normally if we want to increment in the child process we do if(fork()==0)++i; but when we do fork like this, i get a little lost in the middle! – Bruno Jan 28 '10 at 22:20
  • 1
    As per answer: child increments child, parent increments parent, never the twain will meed. – bmargulies Jan 29 '10 at 01:13

5 Answers5

25

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
  • 97,814
  • 39
  • 186
  • 310
17

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
  • 208,748
  • 37
  • 389
  • 560
5

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.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
3

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.

2

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
  • 5,406
  • 2
  • 25
  • 28