Search code examples
clinuxunixforkpid

fork tree C, child processes PID


I have to implement fork tree as in this picture.

               +----+
      +--------| P1 |---------+
     /         +----+          \
    /         /     \           \
 +----+   +----+     +----+   +----+
 | P2 |   | P3 |     | P4 |   | P5 |
 +----+   +----+     +----+   +----+
           /  \                /   \
      +----+ +----+        +----+ +----+
      | P6 | | P7 |        | P8 | | P9 |
      +----+ +----+        +----+ +----+
               |
             +-----+
             | P10 |
             +-----+

Output must return something like:

   P1: pid: 1337 ppid: 1336 child processes pids: 1338, 1339, 1340, 1341
   P2: pid: 1338 ppid: 1337 child processes pids: 1342, 1342... etc.

where the child processes pids are pids of every child process of PX, and I don't know how to go about it. Can you give me some advie? My code so far is below, it creates the tree correctly imo, the child processes are a problem.

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

    int main(int argc, char *argv[])
   {
       int pidp1;
      int pidp2;



switch (pidp1 = fork())
{
    case 0:
        printf("P2: pid: %d ppid: %d\n", getpid(), getppid());
        exit (0);
        break;
    case -1:
        printf("Blad funkcji\n");
        exit (1);
    default:
        printf("P1: pid: %d ppid: %d child processes pids: %d\n", getpid(), getppid(), pidp1);
        wait(NULL);
        switch (pidp1 = fork())
        {
            case 0:
                printf("P3: pid: %d ppid: %d\n", getpid(), getppid());
                switch (pidp1 = fork())
                {
                    case 0:
                        printf("P6: pid: %d ppid: %d \n", getpid(), getppid());
                        exit (0);
                        break;
                    case -1:
                        printf("Blad funkcji\n");
                        exit (1);
                    default:
                        wait(NULL);
                        switch (pidp1 = fork())
                        {
                            case 0:
                                printf("P7: pid: %d ppid: %d\n", getpid(), getppid());
                                switch (pidp1 = fork())
                                {
                                    case 0:
                                        printf("P10: pid: %d ppid: %d\n", getpid(), getppid());
                                        exit (0);
                                        break;
                                    case -1:
                                        printf("Blad funkcji\n");
                                        exit (1);
                                    default:
                                        wait(NULL);
                                        exit (0);
                                }
                                exit (0);
                                break;
                            case -1:
                                printf("Blad funkcji\n");
                                exit (1);
                            default:
                                wait(NULL);
                                exit (0);
                        }
                        exit (0);
                }
                exit (0);
                break;
            case -1:
                printf("Blad funkcji\n");
                exit (1);
            default:
                wait(NULL);
                switch (pidp1 = fork())
                {
                    case 0:
                        printf("P4: pid: %d ppid: %d\n", getpid(), getppid());
                        exit (0);
                        break;
                    case -1:
                        printf("Blad funkcji\n");
                        exit (1);
                    default:
                        wait(NULL);
                        switch (pidp1 = fork())
                        {
                            case 0:
                                printf("P5: pid: %d ppid: %d\n", getpid(), getppid());
                                switch (pidp1 = fork())
                                {
                                    case 0:
                                        printf("P8: pid: %d ppid: %d\n", getpid(), getppid());
                                        exit (0);
                                        break;
                                    case -1:
                                        printf("Blad funkcji\n");
                                        exit (1);
                                    default:
                                        wait(NULL);
                                        switch (pidp1 = fork())
                                        {
                                            case 0:
                                                printf("P9: pid: %d ppid: %d\n", getpid(), getppid());
                                                exit (0);
                                                break;
                                            case -1:
                                                printf("Blad funkcji\n");
                                                exit (1);
                                            default:
                                                wait(NULL);
                                                exit (0);
                                        }
                                        exit (0);
                                }
                                exit (0);
                                break;
                            case -1:
                                printf("Blad funkcji\n");
                                exit (1);
                            default:
                                wait(NULL);
                                exit (0);
                        }
                        exit (0);
                }
                exit (0);
        }
        exit (0);
}
}

Solution

  • Seeing as how this is homework, I'll try to give you some pointers.

    Wow, that's a lot of code! There might be an opportunity here to take some of the code and put it into a function.

    The tree you've linked is a bit weird-looking (not symmetrical), and it starts counting at 1, which is annoying. Nonetheless, we could describe the tree with two arrays: the number of children for each process, and the first number of its leftmost child.

    /* The number of children for P0, P1, P2, P3, ... */
    const int num_children[] = { -1, 4, 0, 2, 0, 2, 0, 1, 0, 0, 0 };
    
    /* The P-number of the first child for P0, P1, P2, P3, ... */
    const int first_child[] = { -1, 2, -1, 6, -1, 8, -1, 10, -1, -1, -1 };
    

    You should be able to recreate the tree from your picture using only this information, and without actually looking at the picture. (Really, do it - I might have made a mistake.)

    Then you could write a function that takes a P number, and does the following:

    • Look up the number of children we have to make in num_children.
    • Look up the P number of the first child in first_child.
    • Fork a few times, each time running our function in the child, with the right P number, and storing the child's pid in the parent somewhere.
    • Output the line you're describing in your question. You've stored all the child pids already, so that should be easy.
    • Wait for its own children to complete.

    Launch the whole thing with yourfunction(1).

    The leaf functions do not have children, so they would wait forever. That means your program does not quit anymore. Ever. This is actually good news: it means you can use Linux tools like ps, pstree, and htop to make sure your tree has the right shape.

    (The lines of output will probably be output in a random order - I hope that's okay.)

    Good luck!