fork函数执行后进程起点疑惑:代码运行结果与预期不符
问题拆解:为什么fork后出现多次"do"?
嘿,我来帮你把这个问题掰明白!你遇到的核心矛盾,其实是**printf的行缓冲机制**和fork()的进程复制特性共同导致的,咱们一步步拆解:
首先先把你的代码贴出来方便分析:
#include<stdio.h> int main(){ printf(" do "); if(fork()!=0) printf("ma "); if(fork()==0) printf("to \n"); else printf("\n"); }
第一个关键:printf的行缓冲坑
默认情况下,printf在终端输出时采用行缓冲策略——意思是:只有遇到换行符\n、缓冲区被填满,或者程序退出的时候,才会把缓冲区里的内容真正输出到屏幕上。
你写的第一个printf(" do ");没有换行符,所以" do "这段内容会暂时存在进程的输出缓冲区里,并没有立刻打印到屏幕!
第二个关键:fork()会复制缓冲区
当你调用fork()时,操作系统会创建一个和父进程几乎完全一样的子进程——包括父进程当前的内存状态,当然也包括输出缓冲区里的内容!
这就意味着:父进程缓冲区里没来得及输出的" do ",会被复制给每个新创建的子进程。等到后续某个操作触发缓冲区刷新时,每个进程都会把这段" do "输出一次,这就是你看到多次"do"的原因。
一步步走代码执行流程
咱们来模拟整个执行过程,更直观:
- 初始父进程P0:执行
printf(" do ");,缓冲区内容为" do ",未输出。 - 第一次调用
fork():创建子进程P1。此时P0和P1的缓冲区里都存着" do "。- P0(父进程):
fork()返回非0,执行printf("ma ");,缓冲区变为" do ma "。 - P1(子进程):
fork()返回0,跳过第一个if,缓冲区还是" do "。
- P0(父进程):
- 接下来P0和P1各自执行第二个
fork():- P0执行第二个
fork(),创建P2:- P0:
fork()返回非0,执行printf("\n");——换行符触发缓冲区刷新,输出" do ma \n"。 - P2:
fork()返回0,执行printf("to \n");——换行触发刷新,输出缓冲区的" do ma "加上"to \n",即" do ma to \n"。
- P0:
- P1执行第二个
fork(),创建P3:- P1:
fork()返回非0,执行printf("\n");——刷新缓冲区,输出" do \n"。 - P3:
fork()返回0,执行printf("to \n");——刷新缓冲区,输出" do to \n"。
- P1:
- P0执行第二个
因为多个进程是并发执行的,终端输出的顺序可能会混乱,最终就会出现你看到的类似do ma do ma to do to do的结果——本质是每个进程都输出了自己缓冲区里的" do "。
验证解决方案
如果想让输出符合你的预期,只需要让第一个printf立刻刷新缓冲区就行,比如加上换行符:
printf(" do \n");
这样" do "会被立刻输出,缓冲区清空,后续fork()复制的就是空缓冲区,就不会出现多次"do"了。
内容的提问来源于stack exchange,提问作者nnnn
相关产品推荐
相关产品推荐

