首页 > 解决方案 > 有没有办法更好地路由流程?

问题描述

我尝试使用 fork() 创建一个进程树,以便每个父级的子级数在给定数组中,例如,如果数组是 {2,1,3,0,0,0,0},则树看起来像这样:

                |   a   |
                /       \
             | b |     |  c  |
             /         /  |  \                 
          | d |   | e | | f | | g |

通过检查从 fork() 返回的值是否为 0,我能够创建进程并将父进程与子进程分开。我设法创建了一个进程树,但我设法创建的树是对称的,而不是什么我真的很想建造。我无法弄清楚兄弟姐妹之间路由过程的部分,

如何分别检查每个进程应该为它创建多少个子进程,并为它创建而不为其他兄弟进程创建?

这是我到目前为止得到的:

int main() {
    int nums[7] = { 2,1,3,0,0,0,0 };
    int pid, pid2;
    size_t len = sizeof(nums)/sizeof(int);
    int childs2;
        printf("\nProcess number %d has pid= %d\n", 0, getpid());
        int childs = 1;
        while( childs <= nums[0] ) {
            pid = fork();
            if (pid == 0 ) {
                printf("Process number %d has pid= %d\n", childs, getpid());
                printf("I am Process with pid=%d and my parent pid=%d\n", getpid(), getppid());
                waitpid(getppid());
                for (int i=1; i<len; i++) {
                    childs2 = 0;
                    if (childs2 < nums[i]) {
                        pid2 = fork();
                        if (pid2 == 0) {
                            printf("Process number %d has pid= %d\n", childs, getpid());
                            printf("I am Process with pid=%d and my parent pid=%d\n", getpid(), getppid());
                            waitpid(getppid());
                            break;
                        } else {
                            wait(NULL);
                            childs2++;
                        }
                    } else {
                        childs2++;
                    }
                }
                break;
            } else {
            wait(NULL);
            childs++;
            }
        }
    return 0;
}

我必须区分进程才能知道哪个进程是叶子,哪个进程是父进程。为此,我需要在每个过程中执行不同的操作,但我想不出办法,

我的输出是:

Process number 0 has pid= 98431
Process number 1 has pid= 98432
I am Process with pid=98432 and my parent pid=98431
Process number 1 has pid= 98433
I am Process with pid=98433 and my parent pid=98432
Process number 1 has pid= 98434
I am Process with pid=98434 and my parent pid=98432
Process number 2 has pid= 98435
I am Process with pid=98435 and my parent pid=98431
Process number 2 has pid= 98436
I am Process with pid=98436 and my parent pid=98435
Process number 2 has pid= 98437
I am Process with pid=98437 and my parent pid=98435

树看起来像:

                |   a   |
                /       \
             | b |      | c |
             /   \      /   \                 
          | d | | e || f | | g |

但我希望输出为:

Process number 0 has pid= 98431
Process number 1 has pid= 98432
I am Process with pid=98432 and my parent pid=98431
Process number 2 has pid= 98433
I am Process with pid=98433 and my parent pid=98431
Process number 3 has pid= 98434
I am Process with pid=98434 and my parent pid=98432
Process number 4 has pid= 98435
I am Process with pid=98435 and my parent pid=98433
Process number 5 has pid= 98436
I am Process with pid=98436 and my parent pid=98433
Process number 6 has pid= 98437
I am Process with pid=98437 and my parent pid=98433

所以树看起来像:

                |   a   |
                /       \
             | b |     |  c  |
             /         /  |  \                 
          | d |   | e | | f | | g | 

.

标签: clinux

解决方案


我们需要做的是跟踪我们在列表中的进程以及孩子在列表中的位置。以下代码显示了如何执行此操作。

#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>


#define NumberOf(a) (sizeof (a) / sizeof *(a))


/*  Create children for process p.

    In a child, return the number of that child process.
    In the parent, return -1.
*/
static int CreateChildren(int NumberOfChildren[], int FirstChild[], int p)
{
    //  Create children for process p.
    printf("Process %d has pid %u and parent %u.\n",
        p, (unsigned) getpid(), (unsigned) getppid());

    for (int i = 0; i < NumberOfChildren[p]; ++i)
    {
        pid_t pid = fork();
        if (pid == -1)
        {
            perror("fork");
            exit(EXIT_FAILURE);
        }
        if (pid == 0)
            /*  This is a child process, and it is child i of process p, so
                its process number is FirstChild[p] + i.  Return that.
            */
            return p = FirstChild[p] + i;
    }

    //  Wait for children to finish.
    for (int i = 0; i < NumberOfChildren[p]; ++i)
        wait(0);

    //  Tell caller the parent finished.
    return -1;
}


int main(void)
{
    int NumberOfChildren[] = { 2, 1, 3, 0, 0, 0, 0 };

    size_t N = NumberOf(NumberOfChildren);

    // Check the NumberOfChildren array for consistency.    
    {
        int sum = 0;
        for (size_t n = 0; n < N; ++n)
        {
            if (NumberOfChildren[n] < 0)
            {
                fprintf(stderr,
                    "Error, number of children cannot be negative but is %d.\n",
                    NumberOfChildren[n]);
                exit(EXIT_FAILURE);
            }
            sum += NumberOfChildren[n];
        }

        if (sum != N-1)
        {
            fprintf(stderr,
                "Error, the numbers of children sum to %d desecendants "
                "of the root, but array has %zu elements after the root "
                "element.\n",
                sum, N-1);
            exit(EXIT_FAILURE);
        }
    }

    /*  Compile information about the children -- set FirstChild[n] to the
        index of the element in NumberOfChildren that is for the first child
        of process n.
    */
    int FirstChild[N];
    {
        int NextChild = 1;
        for (int n = 0; n < N; ++n)
        {
            FirstChild[n] = NextChild;
            NextChild += NumberOfChildren[n];
        }
    }

    //  This is the root process.  Set p to its index.
    int p = 0;

    /*  Create children for process p.  When a child is created, it will
        return its process number, and we will loop to create children for it.
    */
    while (p >= 0)
        p = CreateChildren(NumberOfChildren, FirstChild, p);
}

样本输出:

进程 0 的 pid 为 2648,父进程为 2641。
进程 1 的 pid 为 2649,父进程为 2648。
进程 2 具有 pid 2650 和父进程 2648。
进程 3 的 pid 为 2651,父进程为 2649。
进程 4 具有 pid 2652 和父进程 2650。
进程 5 具有 pid 2653 和父进程 2650。
进程 6 具有 pid 2654 和父进程 2650。

推荐阅读