fork()后进程从何处开始执行?为何fork前的printf会出现两次输出?
问题解答
1. fork()执行后子进程的起始执行位置
fork()完成子进程创建后,子进程不会从头执行整个程序,会直接从fork()调用返回的位置开始往后执行,父子进程会获取到不同的fork返回值,之后各自执行对应分支的代码。
2. 输出两次1的原因
你给出的示例代码如下:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main(void) { for (int i = 1; i < 4; i++) { printf("%d", i); int id = fork(); if (id == 0) { printf("Hello\n"); exit(0); } else { exit(0); } } return 0; }
出现两次1的核心原因是标准输出的行缓冲机制:
- 你使用
printf("%d", i)输出数字1时,内容末尾没有加换行符\n,而默认情况下标准输出是行缓冲模式,只有遇到换行符、缓冲区写满、或者程序主动退出/调用fflush时,才会把缓冲区的内容真正输出到终端。 - fork执行前,printf已经把字符
1写入了父进程的标准输出缓冲区,但还没触发刷新动作,此时执行fork()会复制父进程的完整地址空间,其中就包括还没刷新的标准输出缓冲区,所以子进程的输出缓冲区里也会有一个未写入终端的1。 - 后续父子进程各自执行到
exit(0)时,都会触发缓冲区刷新,各自把缓冲区里的1输出到终端,所以最终会出现两次1。 - 子进程后续还会执行带换行符的
printf("Hello\n"),换行符会直接触发缓冲区刷新,所以最终输出结果就是11Hello。
你可以简单验证这个逻辑:把printf("%d", i);改成printf("%d\n", i)加换行,或者在printf之后加一句fflush(stdout);主动刷新缓冲区,再运行程序就只会输出一次1。
内容的提问来源于stack exchange,提问作者tyy
相关产品推荐
相关产品推荐

