«

解读Linux中的fork机制

俞事 发布于 阅读:191


Linux中的fork机制是进程创建的核心系统调用,通过复制现有进程生成新进程。父进程调用fork后,内核执行以下步骤:

  1. 进程控制块复制
    内核创建新的task_struct结构体,复制父进程的PCB信息,包括:

    • 进程状态
    • 打开的文件描述符表
    • 信号处理程序
    • 虚拟内存映射
    • 当前工作目录
  2. 写时复制优化(COW)
    物理内存页不会立即复制,父子进程共享同一内存空间。内核将内存页标记为只读:

    • 当任一进程尝试写入共享页时触发页错误
    • 内核为该进程分配新物理页并复制内容
    • 修改页表项指向新物理页
  3. 资源分配

    • 分配新的PID给子进程
    • 继承父进程的文件描述符表(相同文件打开偏移)
    • 复制父进程的页表项
    • 创建独立的进程内核栈
  4. 返回值处理
    系统调用返回两次:

    • 父进程接收子进程PID
    • 子进程接收0返回值
    • 返回-1表示创建失败(通过检查errno确定错误类型)
  5. 执行差异处理
    内核设置子进程特定属性:

    • 清除挂起信号队列
    • 重置统计信息(如CPU使用时间)
    • 不继承父进程的内存锁(mlock)
    • 清除跟踪标记(ptrace相关)
  6. 与线程创建的差异
    对比pthread_create:

    • 线程共享地址空间、文件描述符等资源
    • fork产生的进程拥有独立地址空间
    • 线程创建不涉及COW机制
  7. vfork变体
    特殊场景优化版本:

    • 子进程共享父进程地址空间
    • 阻塞父进程直到子进程调用exec或exit
    • 避免COW带来的开销
    • 直接操作父进程堆栈存在安全隐患
  8. 执行后续操作
    典型使用模式:
    if (pid == 0) {
    // 子进程执行exec替换镜像
    execve(...);
    } else if (pid > 0) {
    // 父进程可能调用waitpid
    } else {
    // 错误处理
    }

  9. 性能影响因子
    创建开销取决于:

    • 进程地址空间大小
    • 页表项数量
    • 共享内存区域数量
    • 挂载的命名空间数量
    • SECCOMP过滤器复杂度
  10. 现代扩展机制
    补充方案:

    • clone系统调用:更细粒度控制资源共享
    • posix_spawn:组合fork+exec的优化接口
    • PID命名空间:容器环境中的隔离fork行为

取消
微信二维码
微信二维码
支付宝二维码