我正在尝试在 C 中制作 fork() 进程调用图
I'm trying to make a diagram of fork() process calls in C
这是我现在的位置
#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
);
}
}
}
这是我传入 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
-------------------------------
我注意到的第一件事是,对于代码的每个实例 运行,“子”的 PPID 是“父”的 PID,这很好。
但是当我手绘图的时候:
diagram of my output (I'm new so I can't post photos)
为了作业的缘故,应该是一棵平衡树,这样层次的概念才有意义。我希望将每个进程打印为图表中的节点,例如我使用 graphviz 绘制的图表,并且每个节点都应包含其 PID 和级别。
这是极客对极客的一个例子,展示了我所说的级别的意思:
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
我想我编码过度了。我应该如何更改我的代码以在循环中分叉它并获得树状结构?我正在尝试使用变量 x 来表示级别,但我不确定它是否有效,因为输出的结构对我来说非常意外。
你的直觉错了。在循环的每次迭代中,所有 您的进程将分叉并创建一个新进程 - 不仅是在上一次迭代中创建的进程。
因此,经过 4 次迭代,您会期望初始过程以四个 children:
结束
- 一有3children(图中55)
- 一有2children(图中63)
- 一个有 1 个 child(图中为 67);和
- 无child仁(图中69)
这正是您最终得到的结果。如果您对这些 children 中的每一个都遵循相同的逻辑,并适当减少剩余循环迭代的数量,您将完全重现您拥有的图表。
This question 并非完全相同,但涵盖了大部分相同的领域。
当然,您的图表是一棵树 - 它不是完全平衡的二叉树。要获得这样的结果,您必须在每次循环迭代期间按照以下方式执行更多操作:
- 分叉进程两次
- 在每个 children 中,立即继续下一个循环迭代(这样在下一个迭代之前它们都不会再次分叉)
- 在 parent 中,分叉后完全脱离循环,这样它就不会再次分叉,永远
例如:
#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;
}
带输出,显示完全平衡的二叉树:
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
这是我现在的位置
#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
);
}
}
}
这是我传入 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
-------------------------------
我注意到的第一件事是,对于代码的每个实例 运行,“子”的 PPID 是“父”的 PID,这很好。
但是当我手绘图的时候: diagram of my output (I'm new so I can't post photos)
为了作业的缘故,应该是一棵平衡树,这样层次的概念才有意义。我希望将每个进程打印为图表中的节点,例如我使用 graphviz 绘制的图表,并且每个节点都应包含其 PID 和级别。
这是极客对极客的一个例子,展示了我所说的级别的意思:
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
我想我编码过度了。我应该如何更改我的代码以在循环中分叉它并获得树状结构?我正在尝试使用变量 x 来表示级别,但我不确定它是否有效,因为输出的结构对我来说非常意外。
你的直觉错了。在循环的每次迭代中,所有 您的进程将分叉并创建一个新进程 - 不仅是在上一次迭代中创建的进程。
因此,经过 4 次迭代,您会期望初始过程以四个 children:
结束- 一有3children(图中55)
- 一有2children(图中63)
- 一个有 1 个 child(图中为 67);和
- 无child仁(图中69)
这正是您最终得到的结果。如果您对这些 children 中的每一个都遵循相同的逻辑,并适当减少剩余循环迭代的数量,您将完全重现您拥有的图表。
This question 并非完全相同,但涵盖了大部分相同的领域。
当然,您的图表是一棵树 - 它不是完全平衡的二叉树。要获得这样的结果,您必须在每次循环迭代期间按照以下方式执行更多操作:
- 分叉进程两次
- 在每个 children 中,立即继续下一个循环迭代(这样在下一个迭代之前它们都不会再次分叉)
- 在 parent 中,分叉后完全脱离循环,这样它就不会再次分叉,永远
例如:
#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;
}
带输出,显示完全平衡的二叉树:
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