Reputation: 337
Based on the code below, I have been trying to make a process tree. At first I was thinking it would be similar to a binary tree that is symmetric, but no longer think so.
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
int main() {
int status;
pid_t i;
i = fork();
wait(&status);
printf("a; i = %d\n", i);
i = fork();
wait(&status);
printf("b; i = %d\n", i);
i = fork();
wait(&status);
printf("c; i = %d\n", i);
i = fork();
wait(&status);
printf("d; i = %d\n", i);
return 0;
}
Also, when running this code, there are 2x as many output as I have originally predicted. For example, d
is printed out 16 times, but I figured it would only be printed out 8 times. Any deeper explanation would be helpful.
Upvotes: 1
Views: 89
Reputation: 753475
To help yourself understand, include PID and PPID in each printf()
statement. Also, capture and report the value (dead child PID) returned by wait()
each time it is called; you can decide whether to report status
or not, but initialize it to zero in case (for when) the wait()
calls fail because there is no child. The children continue before the parent returns from the wait()
calls, in general.
Or, better, write a logging function that can handle the details for you. For example, consider this code:
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
static void print_info(const char *tag, int corpse, int status, int child)
{
int pid = getpid();
int ppid = getppid();
printf("PID %5d, PPID %5d: %s (corpse: %5d, status 0x%.4X), child %5d\n",
pid, ppid, tag, corpse, status, child);
}
int main(void)
{
int pid = getpid();
int ppid = getppid();
printf("Initial PID %5d, PPID %5d:\n", pid, ppid);
int status = 0;
int child = fork();
int corpse = wait(&status);
print_info("a", corpse, status, child);
child = fork();
corpse = wait(&status);
print_info("b", corpse, status, child);
child = fork();
corpse = wait(&status);
print_info("c", corpse, status, child);
child = fork();
corpse = wait(&status);
print_info("d", corpse, status, child);
return 0;
}
A sample run gives me:
Initial PID 7357, PPID 20754:
PID 7358, PPID 7357: a (corpse: -1, status 0x0000), child 0
PID 7359, PPID 7358: b (corpse: -1, status 0x0000), child 0
PID 7360, PPID 7359: c (corpse: -1, status 0x0000), child 0
PID 7361, PPID 7360: d (corpse: -1, status 0x0000), child 0
PID 7360, PPID 7359: d (corpse: 7361, status 0x0000), child 7361
PID 7359, PPID 7358: c (corpse: 7360, status 0x0000), child 7360
PID 7362, PPID 7359: d (corpse: -1, status 0x0000), child 0
PID 7359, PPID 7358: d (corpse: 7362, status 0x0000), child 7362
PID 7358, PPID 7357: b (corpse: 7359, status 0x0000), child 7359
PID 7363, PPID 7358: c (corpse: -1, status 0x0000), child 0
PID 7364, PPID 7363: d (corpse: -1, status 0x0000), child 0
PID 7363, PPID 7358: d (corpse: 7364, status 0x0000), child 7364
PID 7358, PPID 7357: c (corpse: 7363, status 0x0000), child 7363
PID 7365, PPID 7358: d (corpse: -1, status 0x0000), child 0
PID 7358, PPID 7357: d (corpse: 7365, status 0x0000), child 7365
PID 7357, PPID 20754: a (corpse: 7358, status 0x0000), child 7358
PID 7366, PPID 7357: b (corpse: -1, status 0x0000), child 0
PID 7367, PPID 7366: c (corpse: -1, status 0x0000), child 0
PID 7368, PPID 7367: d (corpse: -1, status 0x0000), child 0
PID 7367, PPID 7366: d (corpse: 7368, status 0x0000), child 7368
PID 7366, PPID 7357: c (corpse: 7367, status 0x0000), child 7367
PID 7369, PPID 7366: d (corpse: -1, status 0x0000), child 0
PID 7366, PPID 7357: d (corpse: 7369, status 0x0000), child 7369
PID 7357, PPID 20754: b (corpse: 7366, status 0x0000), child 7366
PID 7370, PPID 7357: c (corpse: -1, status 0x0000), child 0
PID 7371, PPID 7370: d (corpse: -1, status 0x0000), child 0
PID 7370, PPID 7357: d (corpse: 7371, status 0x0000), child 7371
PID 7357, PPID 20754: c (corpse: 7370, status 0x0000), child 7370
PID 7372, PPID 7357: d (corpse: -1, status 0x0000), child 0
PID 7357, PPID 20754: d (corpse: 7372, status 0x0000), child 7372
You can chase through the data, seeing that there are 24 processes for the 4 fork()
calls (after each call, there are 2 processes where there was 1 process before, so after one call there are 2 processes; after 2 calls, 4 processes; and so on), and that the child process exits before the parent gets to continue (so, in this example, PID 7357 is the last to print the a
tag, and the b
tag, and the c
tag, and the d
tag).
Any time you're having difficulty tracing the process tree, use a printing technique similar to this to help you understand what is going on better.
Upvotes: 3