Search code examples
cfork

How many times 'a' is printed? (includes fork in a loop)


Say that we have a global variable int a = 0, how many times will a be printed, and what's the first and end value?

for(int i=0; i<6; i++){
    fork();
    a++;
    printf("a = %d\n", a)
    }
printf("a = %d\n", a);

Here's what I did:

  1. i=0: one more thread is created so I have 2 running now, and both of them print (a=1, a=2), can't know which prints what.
  2. i=1: the two threads make more 2 threads, and so I have 4 total, and 4 of the print for (a=3,4,5,6).
  3. i=3: Now with 8, we get (a=7,8,9,10,11,12,13,14).
  4. with 16, until a=30
  5. with 32, until a=62.

and so far I have 2+4+8+16+32=62 in side of the loop, and all of the processes reach the outside loop for extra 32 so I get 94 prints in total with a=1 first value and a=62 end value.


I would appreciate any feedback about my solution, as of I'm not sure how to test it in code since I can't use fork in windows.
Thanks in advance!


Solution

  • Once fixed and completed as described below, the program prints either 190 or 448 lines in common conditions, depending on where its standard output is directed.

    First, the program will not print anything because printf("a = %d\n", a) does not have a semicolon after it, so the program will not compile and hence will not execute.

    Let’s assume we add the missing semicolon, include <stdio.h> and <unistd.h>, wrap the code in a main routine, and compile and execute in a Unix environment. Then, in the case where the output is going to an interactive device:

    • The standard output stream is line buffered or unbuffered. (Typically the former, but they will have the same effects since all printf format strings end with \n.) Each line will be sent to the device as soon as it is sent to the output stream. So it will be sent before the following fork.
    • Numbering the iterations by the value of i, in iteration 0, one process becomes two, a is incremented from 0 to 1 (separately in each process), and each process prints “a = 1”. So two “a = 1” lines are printed.
    • In iteration 1, two processes become four, a becomes 2, and four “a = 2” are printed.
    • In iteration 2, eight “a = 3” are printed.
    • In iteration 3, 16 “a = 4” are printed.
    • In iteration 4, 32 “a = 5” are printed.
    • In iteration 5, 64 “a = 6” are printed.
    • After the loop, in each of 64 processes, a is 6, and 64 “a = 6” are printed.
    • Thus we have 2 + 4 + 8 + 16 + 32 + 64 + 64 = 190 lines.

    If output is going to a file on disk or to a pipe, it is fully buffered. Let’s assume the buffer is large enough to hold all the output from one process. In this case:

    • Each line is held in the buffer and is only sent to the device when the program is exiting.
    • In iteration 0, one process becomes two, a is incremented from 0 to 1, and each process prints “a = 1” into its buffer. Now each buffer holds “a = 1”.
    • In iteration 1, two processes become four, and each process prints “a = 2” into its buffer.
    • In iteration 2, each of eight processes prints “a = 3” into its buffer.
    • In iteration 3, each of 16 processes prints “a = 4” into its buffer.
    • In iteration 4, each of 32 processes prints “a = 5” into its buffer.
    • In iteration 5, each of 64 processes prints “a = 6” into its buffer.
    • After the loop, each of 64 processes prints “a = 6” into its buffer.
    • Then each process flushes its buffer as it is preparing to exit. Each process contains in its buffer the seven lines “a = 1”, “a = 2”, “a = 3”, “a = 4”, “a = 5”, “a = 6”, and “a = 6”. So each of 64 processes prints seven lines, a total of 448 lines.

    If the lines printed were longer, or there were more of them per process, they could fill the buffer at times, and the processes would print their lines early. Those lines would then not be duplicated by later forks, and the total printed would be somewhere between the minimum (from line buffered output) to the maximum (from fully buffered output that completely fits in the buffer). We could also get fragmented lines due to line endings not coinciding with filling the buffer.