C Processes fork()
I am e开发者_JS百科xploring parent process & child processes concept in UNIX. I wrote this small code thinking that x no. or processes would get created. But it has created a different number -
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argv, char *argc[])
{
int i;
pid_t childpid;
for(i=0; i<3; i++)
{
childpid = fork();
if(childpid == -1)
{
perror("Failed to Fork");
return 1;
}
if(childpid == 0)
printf("You are in Child: %ld\n", (long)getpid());
else
printf("You are in Parent: %ld\n", (long)getpid());
}
return 0;
}
OUTPUT:
You are in Parent: 30410
You are in Child: 30411
You are in Parent: 30410
You are in Child: 30412
You are in Parent: 30411
You are in Parent: 30410
You are in Child: 30413
You are in Child: 30414
You are in Parent: 30412
You are in Parent: 30411
You are in Child: 30415
You are in Child: 30416
You are in Parent: 30413
You are in Child: 30417
I understand that in a fork()
situation a parent or a child might get preference in execution. That's is not bothering me, what's bothering me is the number of processes that are getting executed. Why is it 14? and not some 2^n number which is what would happen if we are executing fork(); fork(); fork()
i.e. fork's one after the other.
What am I missing?
UPDATE: One more clarification -
The
fork
function copies the parent memory image so that the new process receives a copy of the address space of the parent.
What does this mean? Does it mean -
- the child process starts executing after the
fork()
statement? - the child process gets a copy of the parent process variables? so if
x=3
above fork, will the child process see this x as 3?
You have 8 processes there being executed, it's just that some of them are printing more than once because of the loop.
If you sort the output:
You are in Parent: 30410
You are in Parent: 30410
You are in Parent: 30410
You are in Parent: 30411
You are in Parent: 30411
You are in Child: 30411
You are in Parent: 30412
You are in Child: 30412
You are in Parent: 30413
You are in Child: 30413
You are in Child: 30414
You are in Child: 30415
You are in Child: 30416
You are in Child: 30417
then you can see that there are only 8 unique process IDs.
The reason for this is subtle. Because a child process inherits (almost) everything from the parent, it gets the current state of the loop as well. I say "almost" since certain things are different, such as the PID (obviously), parent PID (equally obviously) and certain resource limits (depending on the OS).
So, process 0 when i == 0
forks into two. both with their next cycle at i == 1
. Both of these will fork with their next cycle at i == 2
. And so on.
If you examine the following diagram, you can see the creation process.
____A____
/ | \
B_ C_ D
| \ \
E F G
\
H
The lines /
, |
and \
represent forks at the points where i
is 0
, 1
and 2
respectively.
Note that a process (such as E
) which was created from a parent where i == 1
will only fork with i == 2
. In other words, it was created with |
so its next step is \
.
Similarly, B
that was created with /
(i == 0
) will then only fork with |
(i == 1
) and \
(i == 2
).
If you're interested in other information on fork, see my voluminous essay here, and some details on the internals of different fork options under Linux here.
When you call fork(), the program starts EXACTLY where it was during processing. So you have
i=0, 2 processes
i=1, 4 processes
i=2, 8 processes
as rlibby pointed out in his comment, I forgot to take into account the fact that the processes from each of the original passes are part of the totals. So my math was wrong. It should be:
i=0, 1 process + 1 new (2 total)
i=1, 2 processes + 2 new (4 total)
i=2, 4 processes + 4 new (8 total)
I think that the reason you're seeing so many processes get created is that when you fork
a child process, it's in the middle of the for
loop. Consequently, after it prints out that it's a child, it will then continue looping and forking its own children.
To fix this, just have the children exit after printing that they're children:
if(childpid == 0) {
printf("You are in Child: %ld\n", (long)getpid());
exit(0);
}
By the way, this does explain why you're seeing 2n processes for a loop doing n iterations. On each iteration, each process splits into two processes that then run for the rest of the loop iterations. This means that each iteration doubles the number of processes, so after n iterations you'll see 2n processes.
Hope this helps!
There are only 8 processes. Count the unique process IDs.
I think adding a break instead of adding an exit(0) would also work.
精彩评论