目录

1. 引言

2. fork函数初识

为什么给子进程返回0,父进程返回子进程PID?

为什么一个函数会有两个返回值?

3. fork的内核操作

4. 写时拷贝(Copy-on-Write, COW)

5. fork的常规用法

6. fork调用失败的原因

7. vfork函数(补充内容)

8. 总结


1. 引言

在Linux系统中,进程是资源分配和调度的基本单位。进程的创建是操作系统核心功能之一,而fork函数是其中最基础、最重要的接口。本文将深入探讨fork的工作原理、返回值特性、写时拷贝技术,以及vfork的区别与应用场景。

2. fork函数初识

fork用于从一个已存在的进程中创建一个新进程,新进程称为子进程,原进程称为父进程。

c

#include <unistd.h>
pid_t fork(void);

返回值:

  • 子进程中返回 0

  • 父进程中返回子进程的PID;

  • 出错返回 -1

为什么给子进程返回0,父进程返回子进程PID?
  • 子进程可以通过 getpid() 获取自己的PID,不需要通过返回值;

  • 父进程可能拥有多个子进程,需要返回值来区分具体是哪个子进程;

  • 返回0可以简化子进程的代码逻辑(例如 if (pid == 0) 表示子进程)。

为什么一个函数会有两个返回值?

fork 调用一次,但在内核中会复制出一个新的进程控制块(PCB),两个进程各自从 fork 返回一次,因此看似“返回两次”。

3. fork的内核操作

  1. 分配新的内存块和内核数据结构给子进程;

  2. 将父进程的部分数据结构内容拷贝至子进程;

  3. 将子进程添加到系统进程列表;

  4. fork 返回,调度器决定哪个进程先执行。

注意: fork 之后父子进程的执行顺序由调度器决定,无法假设谁先运行。

4. 写时拷贝(Copy-on-Write, COW)

父子进程在 fork 后共享代码段和数据段,只有当一方尝试修改数据时,才会为修改的那一页分配独立的内存副本。

优点:

  • 提高内存利用率;

  • 延迟内存分配,减少不必要的拷贝;

  • 保证进程独立性。

写时拷贝是Linux内核中一项重要的性能优化技术。

5. fork的常规用法

  • 并行处理: 父进程等待客户端请求,子进程处理具体任务;

  • 执行新程序: 子进程 fork 后调用 exec 族函数执行另一个程序。

6. fork调用失败的原因

  • 系统中进程数超过系统限制;

  • 实际用户进程数超过其限制(ulimit -u)。

7. vfork函数(补充内容)

vfork 也用于创建子进程,但与 fork 有显著不同:

特性 fork vfork
地址空间 子进程复制父进程(写时拷贝) 子进程共享父进程地址空间(不复制)
执行顺序 调度器决定 子进程先执行,直到 exit 或 exec,父进程才恢复
数据安全性 各自独立 子进程修改会影响父进程
用途 通用 主要用于立即 exec 的场景

注意: 现代Linux中 vfork 已被 fork + 写时拷贝优化取代,但了解其差异有助于理解历史设计。

8. 总结

fork 是Linux进程管理的基石,写时拷贝技术使其既高效又安全。理解 fork 的行为是掌握进程控制、守护进程、并发服务器等高级主题的前提。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐