一、printf 缓冲区机制printf 函数不会直接将数据输出到屏幕而是先将数据写入缓冲区。满足以下任一条件时缓冲区内容才会输出到屏幕1缓冲区被写满2强制刷新缓冲区如 \n 换行符可触发缓冲区刷新3进程结束。二、进程退出函数exit () 与 _exit ()1. 核心区别特性exit()_exit()函数类型C 标准库函数Unix 系统调用标准 I/O 缓冲区处理强制刷新并关闭内容输出不刷新直接丢弃数据用户态资源清理执行退出处理函数、资源清理跳过直接终止2. exit () 执行流程exit () 会先完成用户态资源清理再触发内核级进程终止执行用户注册的 “退出处理函数”刷新并关闭标准 I/O 流缓冲区内容强制输出清理进程私有资源调用 _exit() 通知内核回收进程。3. _exit () 执行逻辑_exit()跳过所有用户态操作直接通知内核终止进程不执行退出处理函数不刷新标准 I/O 缓冲区内核直接回收进程资源。4. 用法建议普通单进程程序优先使用 exit()保证缓冲区数据输出、资源正常清理多进程程序父 / 子进程子进程优先用 _exit()避免干扰父进程用户态资源父进程使用 exit()。三、fork 进程复制fork() 是 Linux 系统调用作用是复制当前进程创建一个几乎完全相同的子进程1.基础用法头文件unistd.h函数原型pid_t fork(void)2. 返回值说明整数类型执行场景返回值用途父进程中子进程的 PID正整数识别、管理子进程子进程中0确定子进程身份fork 失败-1失败原因存入全局变量errno如内存不足、进程数达上限3. 关键特性1fork 生成的子进程会继承父进程缓冲区中的所有内容若父进程缓冲区未刷新子进程会复制这份未输出的数据。2子进程会从 fork() 之后的代码继续执行不会重新执行 fork() 之前的代码例1当有\n时打印输出几个A代码思想1初始状态只有 1 个主进程 P0进入 for 循环2第 1 次循环i0P0 执行 fork() → 创建子进程 P1此时有 2 个进程P0、P1两个进程都执行 printf(A\n) → 输出 2 个 A两个进程都执行 ii 变为 1进入下一次循环3第 2 次循环i1P0 执行 fork() → 创建子进程 P2P1 执行 fork() → 创建子进程 P3此时有 4 个进程P0、P1、P2、P34 个进程都执行 printf(A\n) → 输出 4 个 A4 个进程都执行 ii 变为 2循环结束4总输出统计第 1 次循环输出 2 个 A 第 2 次循环输出 4 个 A 6 个 A进程树通用公式对于 for(int i0; in; i) { fork(); printf(A\n); }总进程数2^n总打印 A 的数量2^(n1) - 2n12^2-22 个 An22^3-26 个 An32^4-214 个 An42^5-230 个 A例2当无\n时打印输出几个A代码思想1初始状态只有主进程 P0缓冲区空进入循环 i02第 1 次循环i0P0 执行 fork() → 生成子进程 P1P0 缓冲区[A]执行了 printf(A)P1 缓冲区[A]完全复制了 P0 此时的缓冲区两个进程都执行完 printf(A)进入 i现在 i13第 2 次循环i1P0 执行 fork() → 生成子进程 P2P0 缓冲区[A, A]又执行了一次 printf(A)P2 缓冲区[A, A]复制了 P0 此时的缓冲区P1 执行 fork() → 生成子进程 P3P1 缓冲区[A, A]又执行了一次 printf(A)P3 缓冲区[A, A]复制了 P1 此时的缓冲区四个进程P0, P1, P2, P3都执行完 printf(A)循环结束4进程结束刷新缓冲区P0缓冲区 [A, A] → 输出 2 个 AP1缓冲区 [A, A] → 输出 2 个 AP2缓冲区 [A, A] → 输出 2 个 AP3缓冲区 [A, A] → 输出 2 个 A5总输出2 2 2 2 8 个 A进程树通用公式对于 for(int i0; in; i) { fork(); printf(A); }总进程数2^n每个进程最终缓冲区里有 n 个 A总输出n * 2^n例n2 → 2 * 4 8n3 → 3 * 8 24二者对比情况打印语句缓冲区行为总 A 数量带换行printf(A\n)每次printf后立即清空缓冲区6 个不带换行printf(A)fork时缓冲区被完整复制进程结束才统一输出8 个