为什么 fork() return 这个组合中所有可能的输出?
why does fork() return all possible outputs in this combination?
问题:
我需要 clarification/help 了解 fork() 输出。我知道如何使用 fork() 在 c 中编写更详细和更大的代码,并使用其他概念,如管道、ipc、线程 (posix)。但是我对预测 return 输出的理解很糟糕,这就是为什么我要弄清楚这一点的原因我相信我的案例 1 是正确的,但我的其他案例模棱两可或与此相似,因为我对输出不太了解fork().
我对程序输出的了解还不错,我了解包含 for-loop、while-loop、if/else、数据结构、递归输出的基本算法。
但是,我缺乏关于使用 fork() 的程序如何准确输出以及 parent/child 过程组合如何完全如下所述的知识。
我的方法:
最初我们有一个 parent 进程 运行 p0 然后 pid 派生了一个 child 进程。
因此,所有可能的输出将始终包含 0,因为最初 num=0 并且在第一个 prinf() 语句之前 num 未设置为任何其他数字。
我相信 parent 和 child 流程执行的时间是随机的,因为它可以以任何顺序出现。
情况 1:p0 打印 02,因为可能存在 pid 是 parent 的情况。然后分叉的 child 进程 p1 打印 01。最终答案将是 0201
情况 2:p0 打印 01 因为可能存在 pid 是 child 的情况(它是来自内核的主进程的 child 吗?)。然后分叉的 child p1 是一个 parent 所以它打印 0102。最终答案是 0102
情况 3:p0 打印 00,因为 pid 不是 child 或 parent。然后分叉的 child p1 打印 12 因为它同时是一个 child 和一个 parent 。最终答案是 0012.
情况 4:p0 打印 00,因为它不是 parent 或 child。然后分叉的 child 进程 p1 打印 21 因为它可以同时是 parent 和 child。
最终答案是 0021.
代码:
#include <stdio.h>
int num = 0 ;
int main(int argc, char *argv[])
{
int pid ;
pid = fork() ;
printf("%d",num) ;
if (pid == 0) {
num = 1;
} else if (pid > 0) {
num = 2 ;
}
printf("%d",num) ;
}
答案:0102 或 0012 或 0201 或 0021
我猜你想得太复杂了。 fork()
之后发生的事情是您有两个实例(父子)正在执行,每个实例都执行两个输出操作。
这两个实例是独立的,彼此之间一无所知,因此一个不会等待另一个完成,这就是所谓的竞争条件。唯一的保证是每个进程将首先输出 0
,然后是 1
(或 2
),因为这是每个进程中的操作顺序。但是你不能说这四个输出操作将如何交错。
我们称父进程为 A,子进程为 B。A 总是打印 0
,然后是 2
。 B 总是会打印 0
后跟 1
。 A 相对于 B 的时间未定义。 A 的输出可以在 B 的输出之前、交错或之后打印。
实际上有六种可能的结果,如下所示。但是,您只会看到四种不同的输出模式,因为当输出以 00
.
开头时,您无法判断是先打印 A 还是先打印 B
AABB
0201
ABAB
0021
BAAB
0021
ABBA
0012
BABA
0012
BBAA
0102
问题:
我需要 clarification/help 了解 fork() 输出。我知道如何使用 fork() 在 c 中编写更详细和更大的代码,并使用其他概念,如管道、ipc、线程 (posix)。但是我对预测 return 输出的理解很糟糕,这就是为什么我要弄清楚这一点的原因我相信我的案例 1 是正确的,但我的其他案例模棱两可或与此相似,因为我对输出不太了解fork().
我对程序输出的了解还不错,我了解包含 for-loop、while-loop、if/else、数据结构、递归输出的基本算法。
但是,我缺乏关于使用 fork() 的程序如何准确输出以及 parent/child 过程组合如何完全如下所述的知识。
我的方法:
最初我们有一个 parent 进程 运行 p0 然后 pid 派生了一个 child 进程。
因此,所有可能的输出将始终包含 0,因为最初 num=0 并且在第一个 prinf() 语句之前 num 未设置为任何其他数字。
我相信 parent 和 child 流程执行的时间是随机的,因为它可以以任何顺序出现。
情况 1:p0 打印 02,因为可能存在 pid 是 parent 的情况。然后分叉的 child 进程 p1 打印 01。最终答案将是 0201
情况 2:p0 打印 01 因为可能存在 pid 是 child 的情况(它是来自内核的主进程的 child 吗?)。然后分叉的 child p1 是一个 parent 所以它打印 0102。最终答案是 0102
情况 3:p0 打印 00,因为 pid 不是 child 或 parent。然后分叉的 child p1 打印 12 因为它同时是一个 child 和一个 parent 。最终答案是 0012.
情况 4:p0 打印 00,因为它不是 parent 或 child。然后分叉的 child 进程 p1 打印 21 因为它可以同时是 parent 和 child。 最终答案是 0021.
代码:
#include <stdio.h>
int num = 0 ;
int main(int argc, char *argv[])
{
int pid ;
pid = fork() ;
printf("%d",num) ;
if (pid == 0) {
num = 1;
} else if (pid > 0) {
num = 2 ;
}
printf("%d",num) ;
}
答案:0102 或 0012 或 0201 或 0021
我猜你想得太复杂了。 fork()
之后发生的事情是您有两个实例(父子)正在执行,每个实例都执行两个输出操作。
这两个实例是独立的,彼此之间一无所知,因此一个不会等待另一个完成,这就是所谓的竞争条件。唯一的保证是每个进程将首先输出 0
,然后是 1
(或 2
),因为这是每个进程中的操作顺序。但是你不能说这四个输出操作将如何交错。
我们称父进程为 A,子进程为 B。A 总是打印 0
,然后是 2
。 B 总是会打印 0
后跟 1
。 A 相对于 B 的时间未定义。 A 的输出可以在 B 的输出之前、交错或之后打印。
实际上有六种可能的结果,如下所示。但是,您只会看到四种不同的输出模式,因为当输出以 00
.
AABB
0201
ABAB
0021
BAAB
0021
ABBA
0012
BABA
0012
BBAA
0102