首页 > 解决方案 > 使用 fork() 显示进程树

问题描述

我需要创建一个进程树并在类似于此的图表中显示父级和子级:

这

但是我的结果看起来更像下图:

我不确定我做错了什么,这是我的代码

#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);
    }
}

标签: cfork

解决方案


正如我所说的......你fork()在新创建的子进程中每次迭代只有一次。所以你不能真的期待像树一样的视图,对吧?

为了实现这一点,您可能需要在循环中执行以下操作:

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);
}

所以这里的方法 - 你需要fork两次,立即从左边的孩子返回,继续作为新的父母在右边。

关于更改的更多说明:

  • 你在所有的fprintf()电话中都有一个额外的论点。放弃最后一个file论点。关于该主题有很多警告。
  • 您没有正确填写点文件中的最后一个括号 - 替换(i > n)i == n

通过使用重新设计的循环,输出看起来像这样:

在此处输入图像描述

这看起来更像你想要的。


推荐阅读