fork/exec程序输出不符:B打印两次、C三次的原因解析
进程fork与execvp执行结果差异分析
程序代码
int main(int argc,char *argv[]){ int i; for(i=1;i<3;i++){ if (fork()==0){ printf("A"); execvp("./prog2",&argv[1]); printf("B"); exit(1); } printf("C"); } printf("D"); return 0; }
问题描述
执行命令 ./prog1 后,预期结果为:A打印2次,B打印0次,C打印2次,D打印1次。但实际运行结果为:A打印2次,B打印2次,C打印3次,D打印1次。需要解释差异原因。
差异原因解析
1. B打印2次的原因:execvp执行失败
execvp("./prog2", &argv[1]) 执行失败的核心原因是当前工作目录下不存在可执行文件prog2。当execvp调用失败时,子进程不会被新程序替换,会继续执行后续代码:打印B,然后调用exit(1)退出。因为循环执行了2次,每次fork出的子进程都会走到这一步,所以B被打印2次。
2. C打印3次的原因:printf缓冲区的继承
printf默认采用行缓冲模式,当输出内容不包含换行符时,数据会暂存在进程的用户态缓冲区中,直到缓冲区满、进程退出或显式调用fflush才会刷新到终端。
具体执行流程:
- 第一次循环:
父进程调用fork()创建子进程1,子进程进入if分支执行printf("A")(内容存入缓冲区);父进程则执行printf("C")(内容存入自身缓冲区)。子进程1因execvp失败,打印B后退出,退出时刷新缓冲区输出AB;父进程缓冲区此时存有1个C。 - 第二次循环:
父进程再次调用fork()创建子进程2,此时父进程缓冲区中的C会被复制到子进程2的缓冲区中。父进程继续执行printf("C"),自身缓冲区变为CC;子进程2进入if分支执行printf("A")(缓冲区变为CA),因execvp失败打印B(缓冲区变为CAB),退出时刷新缓冲区输出CAB。 - 循环结束后:
父进程执行printf("D"),缓冲区变为CCD,进程退出时刷新缓冲区输出CCD。
统计下来:父进程输出2个C,子进程2输出1个继承来的C,总共3次C。
3. A和D的次数符合预期
A:每个子进程进入if分支后都会打印1次,共2次。D:只有初始父进程会在循环结束后打印1次。
内容的提问来源于stack exchange,提问作者Mike Balts
相关产品推荐
相关产品推荐

