fork的原理

1. fork 的基本原理

当调用 fork() 时,操作系统会执行以下主要步骤:

  1. 分配新的进程结构:

    • 操作系统会为新进程分配一个新的 task_struct 结构(进程控制块,PCB),它用于存储进程的状态、内存信息、文件描述符等。
  2. 复制进程上下文:

    • 进程地址空间: 操作系统会复制父进程的内存页表,从而子进程获得父进程相同的虚拟地址空间内容。现代操作系统中,通常使用写时复制(Copy-On-Write, COW)技术,避免立即复制物理内存数据,而是将父进程的内存页标记为只读,等到子进程或父进程尝试写入时,才真正复制该页数据。
    • 文件描述符表: 子进程会继承父进程的文件描述符表,但文件描述符的引用计数会增加,以表示它们被多个进程共享。
    • 信号处理 : 子进程继承父进程的信号处理设置(除了一些特殊情况,如 SIGCHLD 信号会被重置为默认处理方式)。
    • 进程 ID: 子进程会获得一个新的进程 ID,与父进程不同,但子进程会继承父进程的进程组 ID 和会话 ID。
  3. 更新进程树关系:

    • 内核会将新创建的子进程加入进程树中,成为父进程的子进程。子进程的 parent 指针指向父进程,父进程的子进程链表会新增该子进程。
  4. 返回值:

    • 对于父进程,fork() 返回子进程的 PID。
    • 对于子进程,fork() 返回 0。

2. fork 的详细步骤

从 Linux 内核源码角度来看,fork() 的实现实际上是通过 do_fork() 完成的,该函数负责创建子进程并复制父进程的各种信息。

具体流程如下:

  1. 调用 do_fork():

    • 用户进程调用 fork() 时,会陷入内核,由内核函数 do_fork() 来处理实际的创建工作。
  2. 复制进程信息:

    • do_fork() 函数会调用 copy_process() 函数,后者负责复制父进程的各种信息。包括创建一个新的 task_struct,复制父进程的内存地址空间(使用 COW),文件描述符表,信号处理表等。
  3. 设置子进程状态:

    • 内核会将新创建的子进程的状态设置为就绪态,等待被调度。
  4. 返回:

    • do_fork() 最后会将子进程的 PID 返回给父进程,并将 0 返回给子进程。

3. 写时复制 (Copy-On-Write, COW)

在内存管理中,COW 技术是 fork() 中一个关键的优化点。父子进程共享同一块物理内存,只是在内存页被写入时才进行实际的物理内存复制。这大大提高了 fork() 的效率,特别是对于不需要立即修改内存的场景,例如 fork 后立即执行 exec,加载新的程序映像。

  • 页表复制 : fork() 时,子进程会继承父进程的页表结构,这样子进程的虚拟内存布局与父进程保持一致。
  • 页表标记: 所有被继承的页表项会被标记为只读。当父或子进程尝试写入内存时,CPU 会触发页错误(page fault),内核在处理页错误时检测到这是 COW 的情况,就会复制该内存页,解除只读限制并重新映射。

4. 进程上下文切换与 fork()

当一个进程调用 fork() 后,子进程进入就绪队列,等待调度程序的调度。当调度程序决定切换到子进程时,子进程会从复制的父进程上下文开始执行。这意味着子进程会从 fork() 的返回点开始执行,只不过它返回的是 0

推荐学习 https://xxetb.xetslk.com/s/p5Ibb

相关推荐
丢丢丢丢丢丢~4 小时前
apache2的默认html修改
linux·运维·服务器
wusam4 小时前
Linux系统管理与编程20:Apache
linux·运维·服务器·apache·shell编程
我不想当小卡拉米5 小时前
【Linux】操作系统入门:冯诺依曼体系结构
linux·开发语言·网络·c++
ChironW5 小时前
Ubuntu 24.04 LTS系统上配置国内时间同步
linux·运维·服务器·ubuntu
苏生要努力6 小时前
第九届御网杯网络安全大赛初赛WP
linux·python·网络安全
若风的雨6 小时前
【DeepSeek】判断两个 PCIe 设备是否属于**同一个 PCIe 子树
linux
江畔独步7 小时前
vim中的查找
linux·编辑器·vim
luck_me58 小时前
k8s v1.26 实战csi-nfs 部署
linux·docker·云原生·容器·kubernetes
不摆烂选手8 小时前
Linux 阻塞和非阻塞 I/O 简明指南
linux·驱动开发·ubuntu·正点原子imx6ull学习笔记
SweerItTer8 小时前
由镜像源配置错误导致的软件包依赖问题
linux·vscode·ubuntu