导读:
现代系统通过使控制流发生突变来对这些情况做出反应,我们把这些突变称为异常控制流(Exceptional Control Flow ECF)。
异常控制流发生在计算机系统各个层次,比如,硬件层,硬件检测到的时间会除非控制突然转移到异常处理程序;操作系统层,内核通过上下文切换将控制从一个用户进程转移到另一个用户进程;应用层,一个进程可以发送信号到另一个进程,而接收者会将控制突然转移到它的一个信号处理程序中,一个程序可以通过回避通常的栈规则,并执行到其他函数中任意位置的非本地跳转来对错误做出反应。
本章题目是 “异常控制流 = Exceptional Control Flow”,实际内容是进程,系统调用,异常,信号等,它们与操作系统(以及系统编程)之间都有着密切的联系,后续的几个章节,例如虚拟内存,系统I/O,网络编程等也都与操作系统(以及系统编程)有着密不可分的联系,这就意味着你在学习本章的时候应该顺带着学习操作系统(以及系统编程)相关的术语和基础知识,能够从高层角度理解一些重要概念:Process Management/Scheduling(进程管理/调度),Memory Management(内存管理),File System(文件系统/管理),Interrupts(中断),Device drivers(设备驱动程序),Networking(网络),IPC(Inter-Process Communication,进程间通信) ...
Control Flow是什么:从处理器开始上电运行,一直到断电关机的时间,PC value组成的形如(a1 a2 a3的连续指令)
为什么要学习:
重点解读:
一、异常
异常是异常控制流的一种形式,它一部分由硬件实现,一部分由操作系统实现。
异常就是控制流中的突变,用来响应处理器状态中的某些变化。
状态变化称为事件。在任何情况下,当处理器检测到有事件发生时,它就会通过叫做异常表的跳转表,进行间接过程调用(异常),到一个专门设计用来处理这类事件的操作系统子程序(异常处理程序)。
异常的类型 : 异步异常是由处理器外部的I/O 设备中的事件产生的。同步异常是执行一条指令的直接产物
二、进程
进程提供给应用程序两个假象:1、独立的逻辑控制流:每个程序似乎独占CPU(由内核通过上下文切换机制来实现);2、私有的空间地址:每个程序似乎独占内存(由内核的虚拟内存机制来实现)
进程就是一个执行中的程序的实例。系统中每个程序都运行在某个进程的上下文中。
从程序员角度来看,可以认为进程总是处于下面三种状态之一:一、运行:要么在CPU上执行,要么在等待被执行且最终会被操作系统内核调度(选中去运行)。二、停止:被挂起,且不会被调度,直到收到信号SIGCONT(这是暂停,不是切换导致的)。三、终止:进程永远地停止了。有三种原因:1.收到一个信号,该信号默认行为是终止进程;2.从主程序返回;3.调用exit函数。
三、上下文切换
操作系统内核使用一种称为上下文切换的较高层形式的异常控制流来实现多任务。内核为每个进程维持一个上下文。
上下文是由程序运行所需的状态组成的,包括存放在内存中的程序的代码和数据,是内核重新启动一个被抢占的进程所需的状态。
当内核决定抢占(暂时挂起)当前进程后,它使用上下文切换机制来将控制转移到新的进程(也是先前被抢占的进程)。上下文切换包括:1、保存当前进程的上下文;2、恢复某个先前被抢占的进程被保存的上下文;3、将控制转移给这个新恢复的进程。
四、系统调用错误处理
当Unix系统级函数遇到错误时,它们通常会返回 -1
并设置全局变量 errno
来表示出错原因。
使用错误处理包装函数来调用系统函数同时处理错误。
五、信号
信号就是一条小消息,它由内核发出,通知进程系统中发生了一个某种类型的事件。Linux系统支持30种不同类型的信号,信号类型用小整数ID来标识,每种信号类型都对应某种系统事件。
信号在内核中的表示如下图所示。pending位向量中维护着待处理信号的集合;blocked位向量中维护着被阻塞地信号集合。
信号处理程序是与主程序同时运行、独立的逻辑流(不是进程)。信号处理程序也可以被其他信号处理程序中断。