I need to create a process tree and display the parent and child in a graph similar to this:
However my result looks more like the image below:
I am not sure of what I am doing wrong, here is my code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void){
int i, status;
printf( "Enter a value for n :");
int n;
scanf("%d", &n);
FILE *file;
file = fopen("./digraph.txt", "w+"); //my output file
fprintf(file, "digraph {\n");
for (i=0; i<n; i++){
fflush(file);
int pid = fork();
if (pid == 0) {//child
if(i == 0) { //first level
fprintf(file, " \"%d\" [ label=\"pid %d, level %d\" ];\n", getppid(), getppid(), i, file);
fprintf(file, " \"%d\" [ label=\"pid %d, level %d\" ];\n", getpid(), getpid(), i +1, file);
fprintf(file, " \"%d\" -> \"%d\";\n", getppid(), getpid(), file);
}else{
fprintf(file, " \"%d\" [ label=\"pid %d, level %d\" ];\n", getpid(), getpid(), i , file);
fprintf(file, " \"%d\" -> \"%d\";\n", getppid(), getpid(), file);
}
}
else {
pid = waitpid(-1, &status, 0);
break;
}
}
if (i>n){
fprintf(file, "}");
fclose(file);
}
}
As I was saying ... You only fork()
once per iteration from within your newly created child process. So you can't really expect a tree-like view, right?
In order to make that happen you probably need something like this going on in your loop:
for (i=0; i<n; i++){
fflush(file);
pid_l = fork();
if (pid_l == 0) { //left child
if(i == 0) { //first level
fprintf(file, " \"%d\" [ label=\"pid %d, level %d\" ];\n", getppid(), getppid(), i);
fprintf(file, " \"%d\" [ label=\"pid %d, level %d\" ];\n", getpid(), getpid(), i + 1);
fprintf(file, " \"%d\" -> \"%d\";\n", getppid(), getpid());
}else{
fprintf(file, " \"%d\" [ label=\"pid %d, level %d\" ];\n", getpid(), getpid(), i + 1);
fprintf(file, " \"%d\" -> \"%d\";\n", getppid(), getpid());
}
return 0;
}
else {
printf("parent: %d left child: %d\n", getpid(), pid_l);
pid_r = waitpid(-1, &status, 0);
}
pid_r = fork();
if (pid_r == 0) { //right child
if(i == 0) { //first level
fprintf(file, " \"%d\" [ label=\"pid %d, level %d\" ];\n", getppid(), getppid(), i);
fprintf(file, " \"%d\" [ label=\"pid %d, level %d\" ];\n", getpid(), getpid(), i + 1);
fprintf(file, " \"%d\" -> \"%d\";\n", getppid(), getpid());
}else{
fprintf(file, " \"%d\" [ label=\"pid %d, level %d\" ];\n", getpid(), getpid(), i + 1);
fprintf(file, " \"%d\" -> \"%d\";\n", getppid(), getpid());
}
}
else {
printf("parent: %d right child: %d\n", getpid(), pid_r);
pid_r = waitpid(-1, &status, 0);
break;
}
}
if (i == n) {
fprintf(file, "}");
fclose(file);
}
So the approach here - you need to fork
twice, return immediately from the left child, continue on the right as the new parent.
A few more notes on the changes:
fprintf()
calls. Just drop that last file
argument. There are a lot of warnings on that topic.(i > n)
with i == n
By using the reworked loop, the output looks something like this:
Which seems more like what you wanted.