Problems with Fork and Printf

Funny going ons with Printf

Unix supports IO operations (open, close, read, write, fseek, ..). It does IO buffering, but, as far as the user is concerned, orders are immediately carried out.
C has standard IO operations (fopen, fclose, scanf, printf, ..). It also does IO buffering (fflush to force write out).
Where Unix does buffering in the system space, C does buffering in the user space. This can lead to some interesting behaviors. Here are three programs, program 1, program 2, program 3, that differ on a single statement:
/* Program 1 */      /* Program 2 */               /* Program 3 */
int main(void){      int main(void){               int main(void){
printf("Roses..\n"); printf("Roses..\n");fflush(); printf("Roses..");
write(1,"Violets");  write(1,"Violets");	   write(1,"Violets");
exit(0);}            exit(0);}                     exit(0);}
If you run Program 1 on a terminal you get
	Roses..
	Violets
because "/n" directed to a terminal results in immediate flush of the program buffer. If you run Program 1 redirecting output to a disk file, you will find there:
	Violets
	Roses..
because "/n" directed to a disk does not results in immediate flush of the program buffer.
If you run Program 2, it will print
	Roses..
	Violets
no matter if output is to the terminal or to a disk file. And if you run Program 3 the output may be either
	Roses..
	Violets
or
	Violets
	Roses..
since the order will depend on scheduling.

Funny going ons with Fork

Here is a simple C program using Fork.
main (){
  int pid;
  int i;
  for (i=0; i<3; i++){
  if ((pid=fork()) <0) {
    printf("Sorry, cannot fork\n");
  } else if (pid == 0) {
    printf("child %d\n", i);
  } else {
    printf("parent %d\n", i);}}
  exit(0);}
QUESTION: How many processes are involved, in total, in this program?

If you say four, the parent and the three children, you are wrong since each child tries to continue the loop as its parent was doing.
If you say an infinite number, you are wrong since the child when it tries to do its own first iteration, it has in i a value that is one greater than in its parent. Thus, since i is limited by 3, iterating and forking will stop.

The correct answer is 8 (thanks to Barry Ortlip for the correct number and the explanation for this result):

QUESTION: If instead of having 3 in the loop we had 5, how many processes we would have in total?

By the way, if we run this program we get as output (not always you will get the lines in this order):

	parent 0
	child 0
	parent 1
	parent 1
	child 1
	parent 2
	child 1
	parent 2
	child 2
	parent 2
	child 2
	child 2
	parent 2
	child 2
That is, we have 14 lines, of which 7 start with "parent" and 7 start with "child". Can you explain why this is so? How many lines would be written if we had 5, not 3, iteration? how many starting with "parent"? how many with "child"?

Real confusion when Fork and Printf get together

I compiled the fork program to a.out and gave the command:
	a.out > temp
Here is its output:
	parent 0
	parent 1
	parent 2
	parent 0
	parent 1
	child 2
	child 0
	parent 1
	parent 2
	parent 0
	child 1
	child 2
	parent 0
	child 1
	parent 2
	child 0
	child 1
	parent 2
	child 0
	parent 1
	child 2
	child 0
	child 1
	child 2
We find 24 lines, 12 starting with "parent", 12 starting with "child". We notice further that we have 4 of each "parent 0", "parent 1", "parent 2", "child 0", "child 1", "child 2".

QUESTION: What is happening? What would happen if we have 5 instead of 3 iterations?

Perhaps this diagram helps:

		P(0)---------------------C(0)
		|                         |
	  +----------+              +----------+
	 P(1)       C(1)           P(1)       C(1)
	 |           |              |          |
     +-------+   +-------+      +-------+   +-------+
    P(2)    C(2) P(2)   C(2)   P(2)    C(2) P(2)   C(2)

ingargiola@cis.temple.edu