进程的概念和特征

这一节要解决的问题只有一个:为什么把程序跑起来这件事,需要发明”进程”这个新概念?

答案不在”进程是程序的一次执行”这句定义里,而在它前面的那段历史——是并发逼出来的。理解了这个因果,后面的四个特征、状态转换、PCB 全都是顺推出来的结论,不需要背。

机制

单道程序时代:程序自己就够了

在单道批处理系统里,内存中始终只有一道程序。它从头跑到尾,独占 CPU、独占内存、独占所有设备,中间没有任何人打扰它。

这种环境有一个非常好的性质:封闭性。程序的执行结果只由它的初始条件决定。今天用这组输入运行,明天用同样的输入再运行,无论中间相隔多久、机器是否繁忙,结果都完全一致。由封闭性又直接得到可再现性。

在这种世界里,“程序”这一个概念就足够描述一切了。想知道机器在干什么,看那段代码跑到第几行就行。

多道程序一引入,程序这个概念就不够用了

为了让 CPU 在某道程序等 I/O 时别闲着,系统开始在内存里同时放多道程序,谁等 I/O 就切到别人。这一步是所有复杂性的源头。

第一个坏消息是**异步性**:每道程序都以不可预知的速度向前推进。它什么时候被切走、切走多久、等的资源什么时候到位,全都不确定。这不是故障,是多道环境下必然且正常的现象。

第二个坏消息是异步性的后果:封闭性没了。当两道程序共享同一个变量时,最终结果取决于它们交替执行的先后次序,而次序是不确定的。于是同样的输入可能得出不同的结果,可再现性跟着一起丢掉。

疑问点:如何准确表述"并发进程失去封闭性"

  1. 并发进程失去封闭性,是指()。 A.多个相对独立的进程以各自的速度向前推进 B.并发进程的执行结果与速度无关 C.并发进程执行时,在不同时刻发生的错误 D 并发进程共享变量,其执行结果与速度有关

这道题的答案是 D,而不是看起来也很像的 A。区分点在于:A 描述的是异步性本身,D 描述的才是”失去封闭性”这个后果。异步性是原因,失去封闭性是结果,题目问的是结果。而且 D 里那个”共享变量”是关键限定——两个进程如果井水不犯河水,各跑各的,速度再不确定也不会互相影响结果。必须有共享,速度的不确定才会传导成结果的不确定。

顺带把 B 也划掉:B 说”结果与速度无关”,那正是保持封闭性的描述,意思刚好反了。

第三个坏消息:程序和”这一次执行”不再一一对应

单道时代,一段代码就对应一次运行,两者可以混为一谈。多道环境下这个对应关系彻底断了:

  • 同一个程序可以被同时运行多次。同时开启两个 bash,二者运行的是磁盘上同一份可执行文件,却是两个独立的执行流,各有各的当前目录、变量取值和执行位置。
  • 反过来,一个执行流也可以在生命周期中途换掉自己的程序。Linux 里 fork 之后调用 exec,代码段被整个替换成新程序,但它仍然是原来那个执行实体(PID 都不变)。

所以”程序”这个静态概念无法回答一个最基本的问题:系统现在到底有几个”正在进行的活动”,各自进行到哪一步了?

于是有了进程

系统需要一个能够描述**“一次具体的、动态的执行过程”**的东西(→ 进程),并且要能把这个过程的全部状态记下来,这样才能在切走之后还原回去。这就是进程:

进程是程序在某个数据集合上的一次运行过程,是系统进行资源分配和调度的独立单位。

定义里有三个词都是有分量的,一个都不能省:

“一次” ——强调这是一个具体的实例,而非代码本身。开启两个 bash 即两次运行、两个进程。

“某个数据集合” ——同一段代码配不同的数据,是不同的进程。这解释了为什么进程必须包含数据段,而不能只有代码。

“资源分配和调度的独立单位” ——这句话点明了进程被发明出来的用途:OS 需要一个记账单位。分内存分给谁?调度调的是谁?回答都是进程。(引入线程之后这句话会被拆成两半,调度单位让给线程,资源分配单位仍留在进程,见 2.1.6。)

进程实体:把这个动态过程”落到实处”

进程是个过程,过程是摸不着的。系统要管理它,必须有一份看得见的东西,这就是**进程实体**(进程映像):

进程实体 = 程序段 + 相关数据段 + PCB
  • 程序段:要执行的代码。
  • 数据段:这次运行用到的原始数据和中间结果——这是”某个数据集合”的落地。
  • PCB:进程标识、当前状态、调度信息、资源清单、现场信息。

三者当中,PCB 是进程存在的唯一标志。创建进程的实质就是创建 PCB,撤销进程的实质就是回收 PCB。程序段可以和别的进程共享(两个 bash 共用一份代码),数据段可以为空,唯独 PCB 一个进程一份、不可或缺——要判断系统里有没有这个进程,就看有没有它的 PCB。

注意”进程”和”进程实体”是两个层次的词:进程强调动态的过程,进程实体强调按下暂停键之后内存里的那份快照。教材说”进程是进程实体的运行过程”,就是在说这层关系。

边界

并发 ≠ 并行

这是全章最基础的一对,也是最容易在选择题里栽跟头的地方。

  • 并发:多个进程在同一时间段内都在推进。宏观上同时,微观上(单核)交替。
  • 并行:多个进程在同一时刻真正同时执行,必须有多个处理单元。

关键结论:单核 CPU 上可以并发,但不能并行。 并行是并发的一个特例,不是同义词。题目里出现”单处理机""同一时刻”这类字眼时要格外警惕。

特征之间不是并列的,是有依赖的

教材把并发、共享、虚拟、异步四个特征平铺着列出来,容易让人误以为它们地位相同。实际上:

并发和共享是最基本的两个特征,虚拟和异步建立在并发之上。

因果链是这样的:因为要提高资源利用率,所以引入并发;有了并发,多个进程就要共享资源;为了让每个进程感觉自己独占资源,才需要虚拟;而并发带来的推进速度不确定,就是异步。

所以如果一道题问”取消并发之后还剩什么特征”,答案是虚拟和异步都会跟着消失。

相对速度由谁决定

疑问点:并发进程的相对速度由什么决定

  1. 并发进程执行的相对速度是()。 A.由进程的程序结构决定的 B.由进程自己来控制的 C.与进程调度策略有关 D.在进程被创建时确定的

其中”程序结构”一项的确切含义需一并厘清。

答案是 C。

这道题把”异步性由谁造成”问得很直白。逐项分析:

  • A 程序结构指的是代码本身的组织方式——有几个循环、几层分支、调用了哪些函数。它决定了这个进程总共要执行多少条指令,但决定不了这些指令什么时候被 CPU 执行。
  • B 由进程自己控制是错的,而且错得最有教育意义:进程恰恰无法控制自己什么时候被切走。 时间片到了就被抢占,这是 OS 的决定,进程没有发言权。这正是异步性的本质。
  • D 创建时确定也是错的。创建时确定的是优先级等初值,但实际推进速度还要看运行期间就绪队列里有谁、系统忙不忙。
  • C 调度策略才是对的。谁先跑、跑多久、什么时候被换下来,全是调度算法说了算。

一句话记法:进程的相对速度不掌握在进程手里,掌握在调度器手里。

对照速查

程序进程
静/动静态动态
存在位置外存(文件)内存(有 PCB)
生命期长期存在有创建有消亡,暂时的
对应关系一个程序可对应多个进程一个进程可先后执行多个程序
组成代码 + 数据程序段 + 数据段 + PCB
是否拥有资源否是(资源分配的独立单位)
特征含义常考边界
并发同一时间段内多个进程都在推进单核可并发,不可并行
共享资源被多进程共同使用分互斥共享(如打印机)和同时共享(如磁盘)
虚拟一个物理实体变多个逻辑实体虚拟处理机、虚拟内存、虚拟设备
异步推进速度不可预知由调度策略决定,进程自己控制不了

考点

  • 程序与进程的区别(几乎年年以选择题形式出现)
  • 并发 vs 并行的判据是”时间段”还是”时刻”
  • 失去封闭性的准确表述:共享变量 + 结果与速度有关
  • PCB 是进程存在的唯一标志
  • 四个特征的依赖关系:并发和共享最基本

链接