深入理解计算机系统第八章

异常流控制

从给处理器加 电开始 ,直到你断电为止 ,程序计数 器假设 一个值 a1,a2,a3...的序列其中 ,每个 ak 是某 个相应 的指令 Ik 的地址 。每 次从 ak 到 ak+1 的过渡 称为控制转移(controltransfer) 。 这样的控制转移序列叫做处理器的控制流 (flow of control 或 control flow) 。

现代系统通过使控制流发生 突变来对这些 情况做出反应.。—般而言 ,我们把这些突变称为异常 控制流 ( ECF) 。 异常控制 流发生 在计算机系统 的各个层次 。





异常

异常是异常 控制流 的一种 形式,它一部分由硬 件实现 ,一部分由 操作系 统实现 。因为它们 有一部 分是由硬件实 现的, 所以具体细节将随系统的不同而有所不同 。然而 ,对 于每个系 统而言 ,基本的思想都是 相同的 。

异常 ( exception ) 就是控制流 中的突变 ,用来响应处理器状态中的某些 变化。


在任何 情况下 ,当处 理器检 测到有 事件发 生时, 它就会 通过一 张叫做异常表 (exception table) 的 跳转表 ,进 行一个 间接过 程调用 (异常 ),到一个 专门设 计用来 处理这 类事件的操 作系统子程序 ( 异常处 理程序 (exception handler):)., 当异常 处理程序完成 处理后 ,根据引起异常的事件 的类型 ,会发 生以下 3 种情 况中的 一种:

1) 处理 程序将 控制返 回给当 前指令I curr 即当事 件发生 时正在 执行的 指令。

2) 处理 程序将 控制返 回给下一个指令 I next,如 果没有 发生异 常将会 执行的 下一条指令。

3) 处 理程序 终止被 中断的 程序。

异常处理

异常可能会难 以理解 ,因为处理异 常需要 硬件和 软件紧 密合作 。

系统中 可能的 每种类 型的异 常都分 配了一 个唯一 的非负 整数的 异常号 (exceptionber)。其中一 些号码 是由处 理器的 设计者 分配的 ,其 他号 码是由 操作系 统内核 (操 作系统常驻 内存的 部分) 的 设计者 分配的 。

前者的示 例包括 被零除 、缺页 、内 存访问违例 、断点以及 算术运 算溢出 。后者的示 例包括 系统调 用和来 自外部 I/O 设备的 信号。

异常分类


1.中断

中断是 异步发 生的, 是来自 处理器 外部的 I/O 设备 的信号 的结果 。硬件 中断不 是由任何一 条专门 的指令 造成的 ,从 这个意 义上来 说它是 异步的 。硬 件中断 的异常 处理程 序常常称为 中断处 理程序 (interrupt handler)

2.陷阱和系统调用

陷阱 是有意 的异常 ,是 执行一 条指令 的结果 。就像 中断处 理程序 一样, 陷阱处 理程序将控制 返回到 下一条 指令。 陷阱最 重要的 用途是 在用户 程序和 内核之 间提供 一个像 过程一样 的接口 ,叫 做系统 调用。


3.故障

故障由错误情 况引起 ,它可能能够 被故障 处理程 序修正 。当 故障 发生时 ,处理 器将控制 转移给 故障处 理程序 。如果处理 程序能 够修正 这个错 误情况 ,它就 将控制 返回到 引起故障 的指令 ,从 而重新 执行它 。否则 ,处理 程序返 回到内 核中的 abort 例程, abort 例程会终止 引起故 障的应 程序 。

4.终止

终止是 不可恢 复的致 命错误 造成的 结果, 通常是 一些硬件错误 ,比如 DRAM 或者SRAM 位被损 坏时发 生的奇偶错误 。


进程

异常是 允许操 作系统 内核提 供进程 (process) 概念的 基本构 造块, 进程是 计算机 科学中最深刻 、最成功的概念 之一。

系统 中的每 个程序 都运行 在某个 进程的上下文 (context) 中 。上 下文是 由程序 正确运 行所需 的状态 组成的 。这 个状态 包括存 放在内存中的 程序的 代码和 数据, 它的栈 、通 用目的 寄存器 的内容 、程序 计数器 、环 境变 量以及打开 文件描 述符的 集合。

操作 系统内 核使用 一种称 为上下 文切换 (context switch) 的较 高层形 式的异 常控制 流来实现 多任务 。


逻辑控制流

即使在 系统中 通常有 许多其 他程序 在运行 ,进 程也可 以向每 个程序 提供一 种假象 ,好像它 在独占 地使用 处理器 。如 果想用 调试器 单步执 行程序 ,我 们会看 到一系 列的程 序计数器 (PC) 的值 ,这些 值唯一 地对应 于包含在程序 的可执 行目标 文件中 的指令 ,或是包 含在运 行时动 态链接 到程序 的共享对象中 的指令 。这个 PC 值 的序列 叫做逻辑 控制流 ,或者 简称逻 辑流。

并发流

一 个逻辑 流的执 行在时 间上与 另一个 流重叠 ,称为 并发流 (concurrent flow), 这两个流被称 为并发 地运行 。

多个流 并发地 执行的 一般现 象被称 为并发 (concurrency)。 一个进 程和其 他进程 轮流运行的概 念称为 多任务 ( multitasking ) 。 一 个进程 执行它 的控制 流的一 部分的 每一时 间段叫做时间片 。 因此 ,多 任务也 叫做时 间分片 (time slicing)。

注意 ,并 发流的 思想与 流运行 的处理 器核数 或者计 算机数 无关。 如果两 个流在 时间上重叠 ,那 么它们 就是并 发的, 即使它 们是运 行在同 一个处 理器上 。不过 ,有 时我们 会发现确认 并行流 是很有 帮助的 ,它是 并发流 的一个 真子集 。如 果两 个流并 发地运 行在不 同的处理器核 或者计 算机上 ,那么 我们称 它们为 并行流 (parallel flow), 它 们并行地运行 (runningin parallel)。且并行地执行 (parallel execution)。




用户模式和内核模式

为 了使操 作系统 内核提 供一个 无懈可 击的进 程抽象 ,处理 器必须 提供一 种机制 ,限制一个 应用可 以执行 的指令 以及它 可以访 问的地 址空间 范围。处理器 通常是 用某个 控制寄 存器中 的一个 模式位 (mode bit) 来提 供这种 功能的 ,该寄存器 描述了 进程当 前享有 的特权 。当设 置了模 式位时 ,进程 就运行 在内核 模式中 ( 有时叫做 超级用 户模式 )。 一 个运行 在内核 模式的 进程可 以执行 指令集 中的任 何指令 ,并 且可以访 问系统 中的任 何内存 位置。

没有 设置模 式位时 ,进程 就运行 在用户 模式中 。用户 模式中 的进程 不允许 执行特 权指令(privileged instruction), 比 如停止 处理器 、改变 模式位 ,或 者发 起一个 I/O 操作 。也 不允许用户模 式中的 进程直 接引用 地址空 间中内 核区内 的代码 和数据 。任 何这 样的尝 试都会 导致致命的保 护故障 。反之 ,用 户程 序必须 通过系 统调用 接口间 接地访 问内核 代码和 数据。

运 行应用 程序代 码的进 程初始 时是在 用户模 式中的 。进程 从用户 模式变 为内核 模式的唯一 方法是 通过诸 如中断 、故 障或者 陷人系 统调用 这样的 异常。 当异常 发生时 ,控 制传递到 异常处 理程序 ,处理 器将模 式从用 户模式 变为内 核模式 。处 理程序 运行在 内核模 式中,当它返 回到应 用程序 代码时 ,处理 器就把 模式从 内核模 式改回 到用户 模式。


信号

一 种更髙 层的软 件形式 的异常 ,称为 Linux 信号 ,它允许 进程和 内核中 断其他 进程。一个 信号就 是一条小消息 ,它通 知进程 系统中 发生了 一个某 种类型 的事件 。

发送信号

内 核通过 更新目 的进程 上下文 中的某 个状态 ,发送 (递送 ) 一个信 号给目的进程 。发 送信号可以有 如下两 种原因 :

1) 内核 检测到 一个系 统事件 ,比如 除零错误或者 子进程 终止。

2) — 个进程 调用了 kill 函数 (在 下一节 中讨论 ), 显式 地要求内核 发送一 个信号 给目的 进程。 一个进 程可以 发送信 号给它 自己。

接收信号

当目 的进程 被内核 强迫以 某种方 式对信 号的发 送做出 反应时 ,它就 接收了信号 。进程 可以忽 略这个 信号, 终止或 者通过 执行一 个称为 信号处 理程序 的用户 层函数 捕获这 个信号 。

一个 发出而 没有被 接收的 信号叫 做待处 理信号 (pending signal) 在任何 时刻, 一种类型至多 只会有 一 个待处 理信号 。如 果一个 进程有 一个类 型为k 的待处 理信号 ,那么 任何接下 来发送到这个 进程的 类型为 k的信 号都不 会排队 等待; 它们 只是被 简单地 丢弃。 一个进程可 以有选 择性地 阻塞接 收某种 信号。 当一种信号被 阻塞时 ,它仍可以被发送 ,但是产生的待处理信号不会被接收, 直到进 程取消对这种信号的阻塞。

一 个待处理信号最多只 能被接 收一次 。内核 为每个 进程在 pending 位 向量中 维护着待处 理信号 的集合 ,而在 blocked 位向量中维护 着被阻 塞的信 号集合 。只 要传送 了一个类型为 k的 信号, 内核就 会设置 pending 中的第 k位 ,而只 要接收 了一个 类型为 k的信号, 内核就 会清除 penaing 中的第 k位。

非本地跳转

C 语言 提供了 一种用 户级异 常控制 流形式 ,称 为非本 地跳转 (nonlocal jump), 它将控制直 接从一 个函数 转移到 另一个 当前正 在执行 的函数 ,而不 需要经 过正常 的调用 - 返回序列 。非本 地跳转 是通过 setjmp 和 longjmp 函 数来提 供的。

你可能感兴趣的:(深入理解计算机系统第八章)