Reputation: 47
If my interpretation is right, from the following C program one expects to obtain one process tree, where from one father process, three child processes and two grandchild processes are generated:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int num;
pid_t t;
for (num = 0; num < 2; num++) {
t = fork();
if (t == 0)
break;
}
t = fork();
printf("I am the process %d and my father is %d\n", getpid(), getppid());
return 0;
}
However, after compiling and executing, the output turns out to be as follows:
I am the process 2133 and my father is 2127
I am the process 2134 and my father is 2133
I am the process 2137 and my father is 778
I am the process 2135 and my father is 778
I am the process 2138 and my father is 778
I am the process 2136 and my father is 778
As expected, six processes are produced, but four of them are spawned by the process #778. On the other hand, just one of them (#2134) seems to be fathered by the initial process (#2133). In total two process trees have been produced instead of one.
Why this behavior? Does it mean that those above mentioned four processes have been adopted/reclaimed by the process #778?
Upvotes: 2
Views: 347
Reputation: 12698
I have executed your code, by printing at first the pid of the root process, to obtain this output:
$ pru
start: pid == 6024
I am the process 6025 and my father is 6024
I am the process 6024 and my father is 5524
I am the process 6027 and my father is 6025
I am the process 6028 and my father is 6024
I am the process 6026 and my father is 6024
I am the process 6029 and my father is 6026
I can reorder the data to build the tree, starting by process 6024
:
I am the process 6024 and my father is 5524
I am the process 6026 and my father is 6024
I am the process 6029 and my father is 6026
I am the process 6025 and my father is 6024
I am the process 6027 and my father is 6025
I am the process 6028 and my father is 6024
you could have done the same, by looking that process 6024 shows a completely different parent (in this case 5524) that is not in the list of processes.
In your case, the output is bad (or you have retouched it or the posted code is not the same that produced that output) as the process tree is not the one shown here.
6024
executes the full loop, and so, executes three fork()
s, creating tree more processes (two in the loop and one after it).6025
and 6026
) break
the loop, and execute the fork()
outside the loop, creating one process each, by calling the fork()
that is outside the loop. giving you processes 6027
and 6029
, resp.The output you show, cannot be arranged in this tree structure, if we sort the lines:
I am the process 2133 and my father is 2127
I am the process 2134 and my father is 2133
I am the process 2137 and my father is 778
I am the process 2135 and my father is 778
I am the process 2138 and my father is 778
I am the process 2136 and my father is 778
as only process 2134
is a child of other process... and that is not a tree.
I have read in the comments to your question that for some reason the children have been reparented to the shell. In UNIX no process is reparented to another parent, except when it's parent exit()
s *by any means), in which case, they are reparented to process with PID=1 (the init
or systemd
process, and this is what makes pid 1 special) So your process can be reparented, but never to a different process than the one with PID=1. Indeed, you can check if your parent has died, by testing the result of getppid()
as, if it returns 1
, then your parent is not alive anymore.
Finally, there's plenty of documentation about this schema and the unix process structure, but if I had to recommend you to read about it, I should refer you to the POSIX specifications, available from The Open Group
Upvotes: 1
Reputation: 57185
As pointed out in the comments, you're not waiting for the children to finish in the parent, so orphaned processes are being reclaimed by the shell after their parents exit.
The correct tree structure is:
1
|
2
/ | \
3 4 5
| |
6 7
where:
break
Here's cleaned-up code that will give comprehensible output:
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
printf("original process is %d\n", getpid());
for (int num = 0; num < 2; num++) {
if (fork() == 0) { // 0 means child
break;
}
}
fork(); // fork after the loop
printf("I am %d and my parent is %d\n", getpid(), getppid());
while (wait(NULL) > 0) {} // wait for each child process
return 0;
}
Sample output:
original process is 540
I am 540 and my parent is 1
I am 541 and my parent is 540
I am 543 and my parent is 541
I am 542 and my parent is 540
I am 544 and my parent is 540
I am 545 and my parent is 542
Upvotes: 2