Simm
Simm

Reputation: 89

Linux process tree using fork()

I am trying to create the following process tree using the fork() function: enter image description here

I am aware that the code is kind of messy but I'm a begginer and can't understand many things about processes although I tried to. I am waiting for some advice for the code and what an opinion whether this code is correct or not. Thank you in advance.

Upvotes: 1

Views: 2224

Answers (2)

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136256

You may like to break down the task into primitive steps:

  1. Write a function that creates one child process that executes the function you provided.
  2. Reuse the function to create the required tree of processes.

Example:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int level = 1;
char const offsets[] = "\t\t\t\t\t\t\t\t";

pid_t create_child_process(int(*child_fn)()) {
    // Flush the output buffers to avoid duplicate output from the child process.
    fflush(stdout);
    fflush(stderr);

    pid_t child_pid = fork();
    switch(child_pid) {
    case 0: // Child process.
        ++level;
        exit(child_fn());
    case -1: // fork() failed.
        abort();
    default: // Parent process.
        printf("%.*s %u spawned %u\n", level, offsets, (unsigned)getpid(), (unsigned)child_pid);
        return child_pid;
    }
}

void wait_for_any_child() {
    int wstatus;
    pid_t child_pid = wait(&wstatus);
    if(child_pid == -1)
        abort();
    printf("%.*s %u terminated\n", level, offsets, (unsigned)child_pid);
}

int p2() { return 0; }
int p5() { return 0; }
int p6() { return 0; }
int p7() { return 0; }

int p4() {
    create_child_process(p5);
    create_child_process(p6);
    create_child_process(p7);
    wait_for_any_child();
    wait_for_any_child();
    wait_for_any_child();
    return 0;
}
int p3() {
    create_child_process(p4);
    wait_for_any_child();
    return 0;
}

int p1() {
    printf("%u started\n", (unsigned)getpid());
    create_child_process(p2);
    create_child_process(p3);
    wait_for_any_child();
    wait_for_any_child();
    printf("%u terminated\n", (unsigned)getpid());
    return 0;
}

int main() {
    return p1();
}

Output:

5962 started
     5962 spawned 5963
     5962 spawned 5964
     5963 terminated
         5964 spawned 5965
             5965 spawned 5966
             5965 spawned 5967
             5965 spawned 5968
             5966 terminated
             5967 terminated
             5968 terminated
         5965 terminated
     5964 terminated
5962 terminated

Upvotes: 2

SKi
SKi

Reputation: 8466

It could be less messy if you use own pid variable for each pid (for example p1, p2 ...). And maybe it help, if you comment which process is running branches:

pid_t p1, p2, p3, p4, p5, p6, p7;

p1 = getpid(); 
p2 = fork();
if (p2 != 0)    
{
    // P1 runs this branch
    p3 = fork();
    if (p3 == 0)
    {
       // P3 runs this branch
        p4 = fork();
        if (p4 == 0)
        {
            // P4 runs this branch
            p5 = fork();
            if (p5 != 0)
            {
                // P4 runs this branch
                p6 = fork();        
                if (p6 != 0)
                {
                    // P4 runs this branch
                    p7 = fork();        
                }           
            }
        }     
    }
}

There may be other problems in in your code. But for example this:

           // create child#1
           fork();

           // create child#2
           fork();

           // create child#3
           fork();

...will spawn tree of 7 childs.

If you are creating a serious program (not just playing with fork), then you need to check result of fork() better, because it can also fail.

Upvotes: 1

Related Questions