#include <sys/wait.h> #include <stdlib.h> #include <unistd.h> #include<stdlib.h> int main(void) { pid_t pids[10]; int i; for (i = 9; i >= 0; --i) { pids[i] = fork(); if (pids[i] == 0) { printf("Child%dn",i); sleep(i+1); _exit(0); } } for (i = 9; i >= 0; --i){ printf("parent%dn",i); waitpid(pids[i], NULL, 0); } return 0; }
What is happening here? How is sleep()
getting executed in the for
loop? When is it getting called? Here is the output:
parent9 Child3 Child4 Child2 Child5 Child1 Child6 Child0 Child7 Child8 Child9 //there is a pause here parent8 parent7 parent6 parent5 parent4 parent3 parent2 parent1 parent0
Please explain this output. I am not able to understand how it’s working. Step by step analysis would be great.
Advertisement
Answer
In the first loop, the original (parent) process forks 10 copies of itself. Each of these child processes (detected by the fact that fork()
returned zero) prints a message, sleeps, and exits. All of the children are created at essentially the same time (since the parent is doing very little in the loop), so it’s somewhat random when each of them gets scheduled for the first time – thus the scrambled order of their messages.
During the loop, an array of child process IDs is built. There is a copy of the pids[]
array in all 11 processes, but only in the parent is it complete – the copy in each child will be missing the lower-numbered child PIDs, and have zero for its own PID. (Not that this really matters, as only the parent process actually uses this array.)
The second loop executes only in the parent process (because all of the children have exited before this point), and waits for each child to exit. It waits for the child that slept 10 seconds first; all the others have long since exited, so all of the messages (except the first) appear in quick succession. There is no possibility of random ordering here, since it’s driven by a loop in a single process. Note that the first parent message actually appeared before any of the children messages – the parent was able to continue into the second loop before any of the child processes were able to start. This again is just the random behavior of the process scheduler – the “parent9” message could have appeared anywhere in the sequence prior to “parent8”.
I see that you’ve tagged this question with “zombie-processes”. Child0 thru Child8 spend one or more seconds in this state, between the time they exited and the time the parent did a waitpid()
on them. The parent was already waiting on Child9 before it exited, so that one process spent essentially no time as a zombie.
This example code might be a bit more illuminating if there were two messages in each loop – one before and one after the sleep
/waitpid
. It would also be instructive to reverse the order of the second loop (or equivalently, to change the first loop to sleep(10-i)
).