# 进程

## 定义

程序描述要执行的指令和数据，可以以可执行文件、脚本等形式存在。**进程**是程序运行时由操作系统管理的执行环境，包括地址空间、已打开的资源和管理信息。一个程序可以启动多个进程，它们的运行状态彼此独立，但可以共享某些内存或资源。

进程中的**线程**是调度和执行的单位：同一进程的线程通常共享进程地址空间与资源，各自具有程序计数器、寄存器和调用栈等执行状态。下面用单线程进程的简化模型说明状态变化。

## 性质

### 地址空间

进程使用虚拟地址空间。一个常见的简化布局包括代码、已初始化数据、零初始化的静态数据、堆和调用栈：

| 区域     | 常见用途                   |
| :----- | :--------------------- |
| 代码     | 存放可执行指令，通常可以只读映射       |
| 数据与BSS | 分别容纳已初始化数据与需要零初始化的静态存储 |
| 堆      | 为动态分配提供空间              |
| 栈      | 保存调用过程需要的状态与局部数据       |

具体分段、地址顺序和增长方向由平台、程序与运行时决定，不是所有系统都遵循同一张示意图。进程地址空间可以映射共享内存或同一份只读代码，独立的虚拟地址空间不代表每个物理页都必须单独复制。

### 状态与转换

在单线程进程的五状态模型中，进程可以处于新建、就绪、运行、阻塞或终止状态：

| 状态 | 含义                |
| :- | :---------------- |
| 新建 | 正在创建，尚未进入就绪队列     |
| 就绪 | 可以运行，等待获得CPU      |
| 运行 | 正在CPU上执行          |
| 阻塞 | 等待I/O或其他事件，暂时不能继续 |
| 终止 | 已退出，系统正在或已经处理其资源  |

调度使就绪转为运行；抢占或时间片到期可使运行转为就绪；需要等待的操作使运行转为阻塞；事件完成后阻塞转为就绪。只有真正需要等待时，I/O请求才会导致阻塞。

这是教学模型。实际系统常以线程为调度单位；多线程进程可以同时有运行、就绪或等待中的线程，不能简单用一个状态概括所有线程。

### 内核管理的信息

内核维护进程标识、地址空间、资源和调度所需信息。这些管理信息通常概括为**进程控制块**（PCB），具体结构和名称随操作系统不同。

页表参与虚拟地址到物理内存的映射与访问权限检查。文件描述符表让进程引用已打开的文件、管道或套接字等资源；不同描述符也可能引用共享的打开文件状态，不能一概认为文件位置总是各自独立。

### 上下文切换

当CPU转去执行另一个线程时，内核需要保存和恢复必要的执行状态，并按需要切换地址空间。切换发生在线程之间；同一进程内的线程通常共享地址空间，跨进程切换则可能需要更换地址空间相关状态。调度器决定下一个运行的线程，见[进程调度](/knowledge/cs/operating-systems/process-scheduling/)。

切换需要时间，期间CPU执行的是内核的保存、恢复和调度工作；实际代价依赖平台、缓存状态和切换类型，不能仅凭这段示意给出固定数值。

## 例子

**等待文件读取**

在单线程模型中，进程发起读取后若必须等待I/O，就从运行转为阻塞；事件完成后进入就绪队列，再由调度器选择运行。若数据已经可用而调用无需等待，则不一定经历阻塞。

## 交互探索

选择调度、等待和完成等事件，查看简化的进程状态转换。它展示单线程模型，不代表一个多线程进程的全部线程状态。

交互演示：进程因哪些事件改变状态？。按事件推进进程，查看就绪、运行和阻塞之间的转换。 请在站点操作演示。

## 练习

1. 关于程序与进程的关系，下列哪一项正确？

   * A.  程序描述待执行的指令和数据，进程是一次运行中的执行环境
   * B.  程序在运行时才装入内存，所以程序是动态的
   * C.  一个可执行文件在系统中最多对应一个进程
   * D.  进程只包含代码，不包含运行时的寄存器与栈

   答案：A

   程序描述指令和数据，可以以可执行文件、脚本等形式存在；进程是一次运行中的执行环境，包含地址空间和资源，其线程还有各自的执行状态。同一个程序可以启动多个进程。

2. 关于进程的内存布局，下列叙述哪些正确？

   * A.  代码段存放机器指令，通常只读且可在多个进程间共享
   * B.  数据段存放已初始化的全局变量和静态变量
   * C.  在常见的可执行文件模型中，BSS区域用于零初始化的静态存储
   * D.  所有系统都规定堆和栈必须沿固定方向生长

   答案：A、B、C

   堆和栈的实际布局与增长方向取决于体系结构和运行时；其余三项描述的是常见的进程布局。

3. 进程等待键盘输入时，处于五状态模型中的哪个状态？

   * A.  新建
   * B.  就绪
   * C.  运行
   * D.  阻塞

   答案：D

   等待键盘输入属于等待事件。此时进程即使获得CPU也不能继续执行，因此处于阻塞状态；等输入到达后才会转为就绪。

4. 在单核CPU上，一个正在运行的进程因时间片用完而被换下，它会转到哪个状态？

   * A.  就绪
   * B.  阻塞
   * C.  终止
   * D.  新建

   答案：A

   时间片用完只剥夺CPU，进程所需的其他资源仍然具备，所以回到就绪队列等待下一次调度，而不是进入阻塞。

5. 下列哪些结构由内核为每个进程分别维护？

   * A.  进程控制块（PCB）
   * B.  页表
   * C.  已打开文件表
   * D.  就绪队列

   答案：A、B、C

   在这个简化模型中，内核记录每个进程的管理信息、地址空间和文件描述符；底层内存或打开文件描述可以在进程间共享。就绪队列用于调度，并不专属于某一个进程。

6. 上下文切换的开销来自哪里？

   * A.  保存当前进程的上下文并恢复下一个进程的上下文，其间CPU不执行用户计算
   * B.  必须把当前进程的代码段从磁盘重新装入
   * C.  必须销毁当前进程的PCB
   * D.  必须清空当前进程的页表

   答案：A

   上下文切换的核心工作是保存和恢复程序计数器与寄存器等现场，这段时间CPU执行内核的切换工作，而不是应用线程的计算。进程被换下并不等于结束，PCB和页表都保留着。
