gpt4 book ai didi

c - 通过管道转发时,递归进程树输出不同

转载 作者:行者123 更新时间:2023-11-30 15:06:19 25 4
gpt4 key购买 nike

我检查了应递归创建进程树的同一段代码:

void proc_recurse(int layer)
{
if(layer<=0) return;
switch(fork()){
case 0:
proc_recurse(layer-1);
printf("%d: child layer = %d\n", getpid(), layer);
break;
case -1:
printf(stderr,"%d: fork failed\n", getpid());
break;
default:
printf("%d: parent \n", getpid());
break;
}
}

int main (int argc, char *argv[]) {
int i;
int n = atoi(argv[1]);
printf("I'm grandParent %d n = %d \n", getpid(), n);

proc_recurse(n);
}

enter image description here

显然,使用管道时结果完全不同。我可以观察到 fork 返回到代码开始的位置(注意输出中重复出现的“grandParent”消息)。谁能向我解释这种差异的本质。

最佳答案

问题是缓冲。如果您在 printf 之后添加对 fflush(stdout) 的调用,问题就会消失:

void proc_recurse(int layer)
{
if(layer<=0) return;
switch(fork()){
case 0:
proc_recurse(layer-1);
printf("%d: child layer = %d\n", getpid(), layer);
break;
case -1:
fprintf(stderr,"%d: fork failed\n", getpid());
break;
default:
printf("%d: parent \n", getpid());
break;
}
fflush(stdout);
}

int main (int argc, char *argv[]) {
int i;
int n = atoi(argv[1]);
printf("I'm grandParent %d n = %d \n", getpid(), n);
fflush(stdout);
proc_recurse(n);
}

尝试运行:

$ ./a.out 5 | less
I'm grandParent 7124 n = 5
7124: parent
7126: parent
7126: child layer = 5
7127: parent
7127: child layer = 4
7127: child layer = 5
7128: parent
7128: child layer = 3
7128: child layer = 4
7128: child layer = 5
7129: parent
7130: child layer = 1
7130: child layer = 2
7130: child layer = 3
7130: child layer = 4
7130: child layer = 5
7129: child layer = 2
7129: child layer = 3
7129: child layer = 4
7129: child layer = 5
<小时/>

问题是,在向终端执行输出时,stdout 通常是无缓冲的或行缓冲的。。但是,一旦通过管道传输输出,就会使用缓冲区(类似于 4K 缓冲区,但这取决于情况)。这意味着“grandParent”行不会立即在主进程的输出中给出,然后 fork 会生成该行,以便子进程现在拥有包含该行的缓冲区的副本,并且当它们写入时最后执行输出,最终得到重复的内容。

这是使用fork等编写程序时的常见错误。在执行fork之前,您应该fflush输出以避免这种情况问题。

关于c - 通过管道转发时,递归进程树输出不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39188824/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com