execvp调用失败时各字符打印次数疑问:为何C打印3次?
execvp调用失败时的字符打印次数分析
当execvp()调用失败时,运行以下代码实际得到C打印3次,但逻辑推导预期是2次,想明确正确结果及原因:
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; }
我的预期是:父进程会将C存入缓冲区,第一次循环后存1个C,第二次循环后存2个C,最终打印CCD;两个子进程各自打印AB后退出,因此预期A打印2次、B打印2次、C打印2次、D打印1次。但实际运行结果为A打印2次、B打印2次、C打印3次、D打印1次。
实际运行结果是正确的,核心原因是**fork()会复制父进程的输出缓冲区**,结合标准输出的行缓冲特性,具体分析如下:
标准输出的行缓冲特性:默认情况下,标准输出采用行缓冲模式,只有遇到换行符、缓冲区满或程序退出时才会刷新缓冲区。
printf("C")未添加换行符,输出内容会暂存在缓冲区中,不会立即打印。具体执行流程:
- 第一次循环(i=1):
- 父进程调用
fork()创建子进程1。 - 子进程1进入if分支:执行
printf("A")("A"进入子进程1的缓冲区),execvp失败后执行printf("B")("B"进入缓冲区),随后exit(1)。exit会自动刷新缓冲区,子进程1输出AB。 - 父进程在
fork()后执行printf("C"),"C"进入父进程的缓冲区,此时缓冲区内容为[C]。
- 父进程调用
- 第二次循环(i=2):
- 父进程调用
fork()创建子进程2,此时父进程缓冲区已有一个"C",子进程2会完整复制该缓冲区,初始缓冲区内容为[C]。 - 子进程2进入if分支:执行
printf("A")(缓冲区变为[C,A]),execvp失败后执行printf("B")(缓冲区变为[C,A,B]),随后exit(1)。exit刷新缓冲区,子进程2输出CAB。 - 父进程在
fork()后执行printf("C"),缓冲区内容变为[C,C]。
- 父进程调用
- 循环结束后:
- 父进程执行
printf("D"),缓冲区变为[C,C,D],return 0触发程序退出时刷新缓冲区,输出CCD。
- 父进程执行
- 第一次循环(i=1):
字符打印次数统计:
- A:子进程1、子进程2各1次 → 共2次
- B:子进程1、子进程2各1次 → 共2次
- C:子进程2输出1次,父进程输出2次 → 共3次
- D:父进程输出1次 → 共1次
内容的提问来源于stack exchange,提问作者Mike Balts
相关产品推荐
相关产品推荐

