简体   繁体   English

我正在尝试在 C 中制作 fork() 进程调用的图表

[英]I'm trying to make a diagram of fork() process calls in C

Here's where I am now这就是我现在的位置

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

main(){   
    int n;
    int i;
    int x = 1;

    printf("\nenter number of forks:\n");
    scanf ("%d",&n);
    printf("\nnow forking %d times....\n\n", n);

    for (i = 1;i <= n; i++){
        int pid = fork();
        if (pid < 0){ 
            return -1;
        }

        if (pid != 0){
            printf("\nI am the parent (
                ppid = %d pid = %d)\n",getppid(),getpid()
            );          
            printf(" x = %d\n",x);

            x++;
            wait();
        }else{
            printf("\nI am the child (
                ppid = %d, pid = %d)\n x = 
                %d\n-------------------------------\n",
                getppid(),getpid(),x
            );
        }
    }
}

and here is my output when I pass in 4:这是我传入 4 时的输出:

enter number of forks:
4

now forking 4 times....


I am the parent (ppid = 26178 pid = 39785)
 x = 1

I am the child (ppid = 39785, pid = 39786)
 x = 1
-------------------------------

I am the parent (ppid = 39785 pid = 39786)
 x = 1

I am the child (ppid = 39786, pid = 39787)
 x = 1
-------------------------------

I am the parent (ppid = 39786 pid = 39787)
 x = 1

I am the child (ppid = 39787, pid = 39788)
 x = 1
-------------------------------

I am the parent (ppid = 39787 pid = 39788)
 x = 1

I am the child (ppid = 39788, pid = 39789)
 x = 1
-------------------------------

I am the parent (ppid = 39786 pid = 39787)
 x = 2

I am the child (ppid = 39787, pid = 39790)
 x = 2
-------------------------------

I am the parent (ppid = 39785 pid = 39786)
 x = 2

I am the child (ppid = 39786, pid = 39791)
 x = 2
-------------------------------

I am the parent (ppid = 39786 pid = 39791)
 x = 2

I am the child (ppid = 39791, pid = 39792)
 x = 2
-------------------------------

I am the parent (ppid = 39785 pid = 39786)
 x = 3

I am the child (ppid = 39786, pid = 39793)
 x = 3
-------------------------------

I am the parent (ppid = 26178 pid = 39785)
 x = 2

I am the child (ppid = 39785, pid = 39794)
 x = 2
-------------------------------

I am the parent (ppid = 39785 pid = 39794)
 x = 2

I am the child (ppid = 39794, pid = 39795)
 x = 2
-------------------------------

I am the parent (ppid = 39794 pid = 39795)
 x = 2

I am the child (ppid = 39795, pid = 39796)
 x = 2
-------------------------------

I am the parent (ppid = 39785 pid = 39794)
 x = 3

I am the child (ppid = 39794, pid = 39797)
 x = 3
-------------------------------

I am the parent (ppid = 26178 pid = 39785)
 x = 3

I am the child (ppid = 39785, pid = 39798)
 x = 3
-------------------------------

I am the parent (ppid = 39785 pid = 39798)
 x = 3

I am the child (ppid = 39798, pid = 39799)
 x = 3
-------------------------------

I am the parent (ppid = 26178 pid = 39785)
 x = 4

I am the child (ppid = 39785, pid = 39800)
 x = 4
-------------------------------

The first thing I notice is that for each instance of the code run, the PPID of the "child" is the PID of the "parent", so that's good.我注意到的第一件事是,对于代码运行的每个实例,“子”的 PPID 是“父”的 PID,所以很好。

But when I draw a diagram by hand: diagram of my output (I'm new so I can't post photos)但是当我手工绘制图表时:我的输出图表(我是新手,所以我不能发布照片)

For the sake of the assignment, it should be a balanced tree so that the idea of a level is significant.为了分配,它应该是一个平衡的树,以便级别的想法很重要。 I'm expected to print each process as a node in a diagram such as I have drawn using graphviz, and each node should include its PID and its Level.我希望将每个进程打印为图表中的一个节点,例如我使用 graphviz 绘制的,并且每个节点都应包括其 PID 和其级别。

Here is an example from Geeks for Geeks showing what I mean by level:这是 Geeks for Geeks 的一个例子,展示了我所说的级别的含义:


       L1       // There will be 1 child process 
    /     \     // created by line 1.
  L2      L2    // There will be 2 child processes
 /  \    /  \   //  created by line 2
L3  L3  L3  L3  // There will be 4 child processes 
                // created by line 3

I think I over coded this.我想我过度编码了这个。 How should I alter my code to fork this in a loop and gain a tree-like structure?我应该如何更改我的代码以在循环中分叉并获得树状结构? I am trying to use the variable x to denote the level, but I am not sure if it is working or not, since the structure of the output is quite unexpected to me.我正在尝试使用变量 x 来表示级别,但我不确定它是否有效,因为输出的结构对我来说非常出乎意料。

Your intuition is at fault.你的直觉有问题。 During each iteration of your loop, all your processes will fork and create a new process - not only the processes that were created on the previous iteration.在循环的每次迭代期间,您的所有进程都将派生并创建一个新进程 - 不仅仅是在上一次迭代中创建的进程。

Thus, with 4 iterations, you'd expect the initial process to end up with four children:因此,通过 4 次迭代,您希望初始过程以四个孩子结束:

  • one with 3 children (55 in your diagram)一个有 3 个孩子(图中 55 个)
  • one with 2 children (63 in your diagram)一个有 2 个孩子(图中 63 个)
  • one with 1 child (67 in your diagram);一个有 1 个孩子(图中 67 个); and
  • one with no children (69 in your diagram)一个没有孩子(你的图中是 69)

and this is precisely what you have ended up with.这正是你最终得到的。 If you follow the same logic with each of those children and an appropriately reduced number of remaining loop iterations, you'll reproduce exactly the diagram that you have.如果您对每个子项都遵循相同的逻辑并适当减少剩余循环迭代次数,您将完全重现您拥有的图表。

This question isn't an exact duplicate, but covers much of the same ground. 这个问题不是完全重复,但涵盖了大部分相同的领域。

Your diagram is a tree, of course - it's just not a completely balanced binary tree.你的图当然是一棵树——它只是不是一个完全平衡的二叉树。 To get such a result, you'd have to do something more along the lines of the following during each loop iteration:要获得这样的结果,您必须在每次循环迭代期间按照以下方式做更多的事情:

  1. Fork the process twice fork 进程两次
  2. In each of the children, continue immediately to the next loop iteration (so that neither of them fork again until the next iteration)在每个孩子中,立即继续下一次循环迭代(这样他们都不会在下一次迭代之前再次分叉)
  3. In the parent, break from the loop altogether after forking, so that it doesn't fork again, ever在父级中,分叉后完全脱离循环,这样它就不会再次分叉

For example:例如:

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

int main(void) {
    int level;

    for ( level = 1; level <= 3; level++ ) {
        pid_t pids[2];

        pids[0] = fork();
        if ( pids[0] == -1 ) {
            perror("fork failed");
            exit(EXIT_FAILURE);
        } else if ( pids[0] == 0 ) {
            continue;
        }

        pids[1] = fork();
        if ( pids[1] == -1 ) {
            perror("fork failed");
            exit(EXIT_FAILURE);
        } else if ( pids[1] == 0 ) {
            continue;
        }

        for ( int i = 0; i < 2; i++ ) {
            if ( waitpid(pids[i], NULL, 0) == -1 ) {
                perror("waitpid failed");
                exit(EXIT_FAILURE);
            }
        }

        break;
    }

    printf("level %d: parent %ld, child %ld\n", level, (long) getppid(), (long) getpid());

    return 0;
}

with output, showing your completely balanced binary tree:带有输出,显示您完全平衡的二叉树:

me@mac:$ ./fork | sort
level 1: parent 62427, child 73103
level 2: parent 73103, child 73105
level 2: parent 73103, child 73106
level 3: parent 73105, child 73107
level 3: parent 73105, child 73109
level 3: parent 73106, child 73108
level 3: parent 73106, child 73111
level 4: parent 73107, child 73110
level 4: parent 73107, child 73114
level 4: parent 73108, child 73112
level 4: parent 73108, child 73116
level 4: parent 73109, child 73113
level 4: parent 73109, child 73117
level 4: parent 73111, child 73115
level 4: parent 73111, child 73118

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM