异常控制流
如果程序计数器一直按照内存相邻的地址来执行指令,那么执行过的指令序列是平滑的。但是这种平滑的过程通常不会长久,因为会有程序调用,返回,跳转等指令,使得平滑流突变。
还有一些突变是由于其他原因引起的,如硬件定时器定期产生信号,事件必须得到处理。或网络适配器收到了一个包,必须存放在内存中等。这种突变称为异常控制流(Exceptional Controal Flow,ECF)。
异常
异常就是控制流中的突变,用来相应处理器状态中的某些变化。
在任何情况下,处理器检测到有事件发生时,就会通过一张叫异常表的跳转表,进行一个间接过程调用,运行专门处理此类事件的操作系统子程序(异常处理程序)。处理完成后根据引起异常的事件类型,回到事件发生时的指令,或发生时的下一条指令,或终止被中断的程序。
异常处理
异常表的结构:
在系统启动时,由操作系统分配和初始化。表的起始地址放在异常表基址寄存器中。
通过异常号与基址,获取异常程序处理地址:
异常的类别
1. 中断
中断是异步发生的,即是来自处理器外部I/O设备的信号的结果。而不是处理器内部指令产生的,所以说是异步的。
外部通过向处理器芯片上的一个引脚发信号,并将异常号放到系统总线上,来出发中断,这个异常好号标识了引起中断的设备。
CPU执行完当前指令会去执行中断程序,然后回到下一条指令继续执行。
2. 陷阱
陷阱是有意的异常,主要用途是在用户程序和内核之间提供一个像过程调用一样的接口,叫系统调用。
比如读文件,创建新进程,加载新程序,终止当前程序,都需要向内核请求服务。处理器提供了一条特殊的 syscall n 指令,来调用服务n。
普通的函数运行在用户模式中,限制了函数可以执行的指令类型,且只能访问与调用函数相同的栈。系统调用运行在内核模式中,内核模式运行系统调用执行特权指令,并访问定义在内核汇中的栈。
3. 故障
故障由错误情况引起,可以被故障处理程序修正。
如果被修复了,会返回时重新执行当前指令。否则,返回到内核的abort例程,会终止引起故障的应用程序。
缺页是一个经典的异常。
4. 终止
终止时不可恢复的致命错误造成的结果,通常是硬件错误。
进程
现代的操作系统会提供给程序一个假象,即程序似乎是独占处理器和内存的。
系统中的每个程序都运行在某个进程上下文中,上下文是由程序正确运行所需的状态组成的,状态包括存放在内存中的程序的代码和数据,栈、通用寄存器内容、程序计数器、变量环境以及打开问阿金描述符集合。
1. 逻辑控制流
一个程序对应的程序计数器的值构成的序列,交逻辑控制流,简称逻辑流。
2. 并发流
一个逻辑流的执行在时间上与另一个流重叠,称为并发流,这两个流被称为并发地执行。
多个流并发地执行一般现象称为并发(concurrency)。一个进程和其他进程轮流运行的概念称为多任务。一个程序执行它的控制流的一部分的每一时间段叫时间片。因此多任务也叫时间分片。
如果两个流并发运行在不同的处理器核或计算机上,则称为并行流(parallel flow),并发地运行,且并行地执行。
3. 用户模式和内核模式
处理器通常用某个控制寄存器中的一个模式位来提欧共这种功能,寄存器描述了进程当前享有的特权。在内核模式的进程可以执行任何指令,且能访问系统中的任何内存位置。
4. 上下文切换
上下文切换是由内核完成的。
在进程执行的某些时刻,内核可以决定抢占当前进程,并重新开始一个先前被抢占了的进程。这种决策叫调度,由内核中的调度器的代码处理的。
上下文切换:
保存当前进程上下文
恢复先前某个被抢占的进程被保存的上下文
将控制传递给这个新恢复的进程
进程控制
获取PID的方法:
进程的创建:
子进程是父进程的一分拷贝,除了PID不同,其他基本相同。(即在不同的地址空间中,有相同的拷贝)
fork之后,子进程会沿着fork之后的那条语句继续执行下去。
僵死进程(僵尸进程)
子进程已经执行完毕,但是内核并不会清除掉子进程,直到被父进程回收。父进程回收子进程时,内核会将子进程的退出状态传递给父进程,然后再抛弃已终止的进程。一个终止了还未被回收的进程称为僵死进程。
pid>0表示进程ID等于PID的子进程。-1表示所有子进程组成的集合。其中一个终止就会返回PID。
信号
一个信号就是一条小消息,通知进程系统中发生了一个某种类型的事件。
通常异常都是由内核异常处理程序进行处理的,正常情况下,对用户进程是不可见的。信号提供了一种机制,通知用户进程发生了这些异常。
传送一个信号到目的进程的步骤: