Sunday面试指南

fork 和 exec 有什么区别?写时复制 COW 是怎么工作的?

下面是一段教学用的模拟面试。

🧑‍💻 面试官:fork 和 exec 有什么区别?

🙋‍♂️ 我:fork 创建子进程,exec 执行另一个程序。

🧑‍💻 面试官:exec 会再创建一个新 PID 吗?

🙋‍♂️ 我:不会,成功以后替换当前进程的程序映像。

🧑‍💻 面试官:那 fork 后父子进程的内存,是马上全部复制吗?为什么写某些页面后,内存才明显增加?

fork 解决「新增进程」,exec 解决「当前进程换程序」。COW 则解释 fork 后内存如何延迟复制。

面试速答(60 秒版)

fork 创建子进程。父子进程在逻辑上拥有独立地址空间,fork 在父进程返回子 PID,在子进程返回零。

Linux 通常通过写时复制 COW 避免立刻复制全部物理页面。父子先共享可共享的页面,当某一方写入相关页面时,再建立私有副本。

exec 不再创建子进程,而是替换当前进程的程序映像,PID 通常保持不变。成功执行后,不会回到旧程序继续运行;失败时才返回错误。

因此,启动新程序常采用 fork 后由子进程 exec。实际使用时,还要处理文件描述符继承、失败退出和父进程回收。多线程进程 fork 后的子进程,只保留调用线程,不能随意执行依赖旧锁状态的代码。

fork 新增,exec 换程序

图:这里画的是父进程写入后得到自己的副本;写时复制并不只允许子进程触发。

知识点详解:从创建子进程,到让子进程运行新程序

fork 返回两次,分支应该由返回值决定

假设一个服务需要启动外部工具。调用 fork 后,父进程继续管理任务,子进程准备运行工具。

这两个进程各自从 fork 返回位置继续执行。父进程拿到子 PID,子进程拿到零;如果创建失败,父进程得到错误。不能把 fork 理解成“把子进程函数传给内核,它就只运行那个函数”。

子进程拥有自己的地址空间视图。普通私有变量的修改,不会自动更新父进程的同一个变量。需要通信时,应采用管道、共享内存等明确机制。

COW 延迟的是物理复制,不是取消逻辑隔离

fork 时,父子可以暂时映射相同物理页面,相关私有可写映射受写时复制保护。

当其中一方写入,内核需要让该进程获得可修改的私有内容,通常会复制相应页面。另一方仍保持原来的数据视图。

所以,“父子共享物理页面”和“父子普通变量相互独立”可以同时成立。COW 的单位也不是某个高级语言变量,而是内存页面等底层映射粒度。

这能解释为什么 fork 初期内存增加相对有限,随后大量改写页面,实际占用才逐步增加。具体行为见 fork 手册。

共享页面,写入时建立私有副本

图:A、B 表示物理页及其映射,不是说进程的虚拟地址随着复制改变了。

exec 成功后,旧程序去哪里了?

exec 会用新程序替换当前进程的代码、数据和运行映像。它不是在旧程序里临时调用一下新程序,然后再返回。

PID 等部分进程身份保持,但并非所有属性都原样保留。文件描述符通常继续存在,除非设置 close-on-exec;信号处理、映射等有相应重置规则,见 execve 手册。

因此,启动外部程序前要决定它应该继承哪些输入输出和文件句柄。忘记关闭不需要的管道端,可能导致另一端一直等不到 EOF。

多线程服务,为什么尤其要谨慎?

fork 后,子进程只保留调用 fork 的那个线程,但内存中可能仍有其他线程留下的锁状态。某把锁如果原来由已消失线程持有,子进程再尝试获取就可能卡住。

因此,在多线程进程的子分支中,到 exec 之前应遵守相应的异步信号安全限制,不随意调用复杂库、日志或分配逻辑。

高级语言中,通常优先使用明确管理创建过程的子进程 API。Python 的 subprocess 和 Node 的子进程 API 各有实现与平台差异,不能用名字相近证明它们都直接执行同一套 fork 路径。本题不提供误导性的对照代码。

地址空间独立,内核资源可能共享

图:地址空间独立,内核资源可能共享。

面试官继续追问

exec 失败以后怎么办?

子进程仍在旧程序中,应记录必要错误并正确退出,不能意外继续父进程的业务路径。父进程还要领取退出状态。

fork 后共享文件描述符,文件偏移也独立吗?

对应描述符可能引用同一个打开文件描述,文件偏移等状态可能共享。独立地址空间不代表所有内核资源都独立。

COW 能保证 fork 毫无成本吗?

不能。进程和页表管理等仍有成本,后续写页面也会产生复制开销。大进程和频繁写入需要实际评估。

面试速记卡

  • fork:新增进程,父子按返回值分支。
  • COW:逻辑隔离,相关物理页面延迟到写时复制。
  • exec:替换当前程序映像,成功不返回旧程序。
  • 资源:明确文件描述符继承与关闭。
  • 多线程:子分支谨慎处理旧锁状态,尽快进入新程序。

公司面试真题

真题根据求职者公开面经整理,题意经过概括,非逐字原话或公司官方题库;本文为 Sunday 的独立解析。

浏览公司面试真题 →
简历汪永久免费在线制作简历,模板直接套用、导出无水印,永久免费、下载免费,不需要付费解锁任何功能。去写简历