'a' 打印了多少次? (包括循环中的 fork)
How many times 'a' is printed? (includes fork in a loop)
假设我们有一个全局变量int a = 0
,a
会打印多少次,第一个和最后一个值是多少?
for(int i=0; i<6; i++){
fork();
a++;
printf("a = %d\n", a)
}
printf("a = %d\n", a);
这是我所做的:
- i=0: 又创建了一个线程,所以我现在有 2 个 运行,它们都打印 (a=1, a=2),不知道哪个打印什么。
- i=1:这两个线程产生了更多的 2 个线程,所以我总共有 4 个,打印的 4 个用于 (a=3,4,5,6)。
- i=3:现在有了 8,我们得到 (a=7,8,9,10,11,12,13,14)。
- 用16,直到a=30
- 用32,直到a=62。
到目前为止,我在循环的一侧有 2+4+8+16+32=62
,并且所有进程都到达外部循环以获得额外的 32,所以我总共得到 94
打印 a=1
第一个值和 a=62
最终值。
我将不胜感激任何关于我的解决方案的反馈,因为我不确定如何在代码中测试它,因为我不能在 windows 中使用 fork。
提前致谢!
按如下所述修复并完成后,程序会在常见情况下打印 190 或 448 行,具体取决于其标准输出的定向位置。
首先,程序不会打印任何东西,因为 printf("a = %d\n", a)
后面没有分号,所以程序不会编译,因此不会执行。
假设我们添加缺少的分号,包括<stdio.h>
和<unistd.h>
,将代码包装在main
例程中,并在Unix环境中编译和执行。然后,在输出到交互设备的情况下:
- 标准输出流是行缓冲或非缓冲的。 (通常是前者,但它们将具有相同的效果,因为所有
printf
格式字符串都以 \n
结尾。)每一行在发送到输出流后都会立即发送到设备。所以会在后面fork
. 之前发送
- 按
i
的值对迭代进行编号,在第0次迭代中,一个进程变成两个,a
从0递增到1(每个进程分别),每个进程打印“一个 = 1”。所以打印了两行“a = 1”。
- 第1次迭代,2个进程变成4个,
a
变成2个,打印出4个“a = 2”。
- 在迭代 2 中,打印了八个“a = 3”。
- 在第 3 次迭代中,打印了 16 个“a = 4”。
- 在第 4 次迭代中,打印了 32 个“a = 5”。
- 在第 5 次迭代中,打印了 64 个“a = 6”。
- 循环后,在64个进程中,每个进程中,
a
为6,打印64个“a = 6”。
- 因此我们有 2 + 4 + 8 + 16 + 32 + 64 + 64 = 190 行。
如果输出到磁盘上的文件或管道,它是完全缓冲的。假设缓冲区足够大,可以容纳一个进程的所有输出。在这种情况下:
- 每一行都保存在缓冲区中,仅在程序退出时才发送到设备。
- 在第 0 次迭代中,一个进程变为两个,
a
从 0 递增到 1,每个进程将“a = 1”打印到其缓冲区中。现在每个缓冲区都包含“a = 1”。
- 在第 1 次迭代中,两个进程变成了四个,每个进程将“a = 2”打印到其缓冲区中。
- 在迭代 2 中,八个进程中的每一个都将“a = 3”打印到其缓冲区中。
- 在第 3 次迭代中,16 个进程中的每一个都将“a = 4”打印到其缓冲区中。
- 在第 4 次迭代中,32 个进程中的每一个都将“a = 5”打印到其缓冲区中。
- 在第 5 次迭代中,64 个进程中的每一个都将“a = 6”打印到其缓冲区中。
- 循环后,64 个进程中的每一个都将“a = 6”打印到其缓冲区中。
- 然后每个进程在准备退出时刷新其缓冲区。每个进程在其缓冲区中包含七行“a = 1”、“a = 2”、“a = 3”、“a = 4”、“a = 5”、“a = 6”和“a = 6” ”。所以64个进程每个打印7行,共448行。
如果打印的行更长,或者每个进程有更多的行,它们有时会填满缓冲区,并且进程会提前打印它们的行。这些行将不会被后来的分叉复制,并且打印的总数将介于最小值(从行缓冲输出)到最大值(从完全适合缓冲区的完全缓冲输出)之间。由于行结束与填充缓冲区不一致,我们还可能得到零散的行。
如果不能 运行,请模拟 fork
。然后,您可以计算 fork
创建的进程数和 a
打印的总数。
如果您想了解这种递归模型发生了什么,您现在可以使用逐步调试。
#include <stdio.h>
int processes = 1;
int prints_of_a = 0;
void fake_fork(int a, int i) {
++ processes;
// behave like fork, start from inside loop
goto start_here;
for(; i<6; i++){
fake_fork(a, i);
start_here:
a++;
//printf("a = %d\n", a);
++ prints_of_a;
}
//printf("a = %d\n", a);
++ prints_of_a;
}
int main(int argc, char * argv[]) {
int a = 0;
for(int i=0; i<6; i++){
fake_fork(a, i);
a++;
//printf("a = %d\n", a);
++ prints_of_a;
}
//printf("a = %d\n", a);
++ prints_of_a;
printf("processes: %d\n", processes);
printf("prints a : %d\n", prints_of_a);
return 0;
}
输出:
processes: 64
prints a : 190
假设我们有一个全局变量int a = 0
,a
会打印多少次,第一个和最后一个值是多少?
for(int i=0; i<6; i++){
fork();
a++;
printf("a = %d\n", a)
}
printf("a = %d\n", a);
这是我所做的:
- i=0: 又创建了一个线程,所以我现在有 2 个 运行,它们都打印 (a=1, a=2),不知道哪个打印什么。
- i=1:这两个线程产生了更多的 2 个线程,所以我总共有 4 个,打印的 4 个用于 (a=3,4,5,6)。
- i=3:现在有了 8,我们得到 (a=7,8,9,10,11,12,13,14)。
- 用16,直到a=30
- 用32,直到a=62。
到目前为止,我在循环的一侧有 2+4+8+16+32=62
,并且所有进程都到达外部循环以获得额外的 32,所以我总共得到 94
打印 a=1
第一个值和 a=62
最终值。
我将不胜感激任何关于我的解决方案的反馈,因为我不确定如何在代码中测试它,因为我不能在 windows 中使用 fork。
提前致谢!
按如下所述修复并完成后,程序会在常见情况下打印 190 或 448 行,具体取决于其标准输出的定向位置。
首先,程序不会打印任何东西,因为 printf("a = %d\n", a)
后面没有分号,所以程序不会编译,因此不会执行。
假设我们添加缺少的分号,包括<stdio.h>
和<unistd.h>
,将代码包装在main
例程中,并在Unix环境中编译和执行。然后,在输出到交互设备的情况下:
- 标准输出流是行缓冲或非缓冲的。 (通常是前者,但它们将具有相同的效果,因为所有
printf
格式字符串都以\n
结尾。)每一行在发送到输出流后都会立即发送到设备。所以会在后面fork
. 之前发送
- 按
i
的值对迭代进行编号,在第0次迭代中,一个进程变成两个,a
从0递增到1(每个进程分别),每个进程打印“一个 = 1”。所以打印了两行“a = 1”。 - 第1次迭代,2个进程变成4个,
a
变成2个,打印出4个“a = 2”。 - 在迭代 2 中,打印了八个“a = 3”。
- 在第 3 次迭代中,打印了 16 个“a = 4”。
- 在第 4 次迭代中,打印了 32 个“a = 5”。
- 在第 5 次迭代中,打印了 64 个“a = 6”。
- 循环后,在64个进程中,每个进程中,
a
为6,打印64个“a = 6”。 - 因此我们有 2 + 4 + 8 + 16 + 32 + 64 + 64 = 190 行。
如果输出到磁盘上的文件或管道,它是完全缓冲的。假设缓冲区足够大,可以容纳一个进程的所有输出。在这种情况下:
- 每一行都保存在缓冲区中,仅在程序退出时才发送到设备。
- 在第 0 次迭代中,一个进程变为两个,
a
从 0 递增到 1,每个进程将“a = 1”打印到其缓冲区中。现在每个缓冲区都包含“a = 1”。 - 在第 1 次迭代中,两个进程变成了四个,每个进程将“a = 2”打印到其缓冲区中。
- 在迭代 2 中,八个进程中的每一个都将“a = 3”打印到其缓冲区中。
- 在第 3 次迭代中,16 个进程中的每一个都将“a = 4”打印到其缓冲区中。
- 在第 4 次迭代中,32 个进程中的每一个都将“a = 5”打印到其缓冲区中。
- 在第 5 次迭代中,64 个进程中的每一个都将“a = 6”打印到其缓冲区中。
- 循环后,64 个进程中的每一个都将“a = 6”打印到其缓冲区中。
- 然后每个进程在准备退出时刷新其缓冲区。每个进程在其缓冲区中包含七行“a = 1”、“a = 2”、“a = 3”、“a = 4”、“a = 5”、“a = 6”和“a = 6” ”。所以64个进程每个打印7行,共448行。
如果打印的行更长,或者每个进程有更多的行,它们有时会填满缓冲区,并且进程会提前打印它们的行。这些行将不会被后来的分叉复制,并且打印的总数将介于最小值(从行缓冲输出)到最大值(从完全适合缓冲区的完全缓冲输出)之间。由于行结束与填充缓冲区不一致,我们还可能得到零散的行。
如果不能 运行,请模拟 fork
。然后,您可以计算 fork
创建的进程数和 a
打印的总数。
如果您想了解这种递归模型发生了什么,您现在可以使用逐步调试。
#include <stdio.h>
int processes = 1;
int prints_of_a = 0;
void fake_fork(int a, int i) {
++ processes;
// behave like fork, start from inside loop
goto start_here;
for(; i<6; i++){
fake_fork(a, i);
start_here:
a++;
//printf("a = %d\n", a);
++ prints_of_a;
}
//printf("a = %d\n", a);
++ prints_of_a;
}
int main(int argc, char * argv[]) {
int a = 0;
for(int i=0; i<6; i++){
fake_fork(a, i);
a++;
//printf("a = %d\n", a);
++ prints_of_a;
}
//printf("a = %d\n", a);
++ prints_of_a;
printf("processes: %d\n", processes);
printf("prints a : %d\n", prints_of_a);
return 0;
}
输出:
processes: 64
prints a : 190