操作系统的执行之中断和双重模式
现代操作系统是通过中断驱动的。
如果没有程序需要执行,没有I/O设备需要服务,没有用户干预,操作系统就会静静的等待某个事件的发生。而事件的发生总是因为中断引起的,这里的中断是广义上的,包括内中断和外中断。
1.中断
中断本质上就是一个信号,用来改变CPU的执行状态的信号。这个信号可以让CPU从一个程序转到另一个程序执行,也可以与用户进行交互。当我们点击鼠标时,或者按下键盘时,就会有信号传递给CPU以此来告知告诉CPU它要执行什么操作,中断又分为内中断和外中断。
2.外中断
外中断就是狭义上的中断,指的是外部设备发送给CPU的信号,也叫做外部硬件中断,或者异步中断。
当外部设备发生错误,或者它完成了操作系统分配给它的任务,这是它就需要通知一下CPU,给CPU发一个信号,这就是外部中断。
同时,外设有很多,发送的信号如果都一样的话,CPU依然不知道是哪一个设备是出错了还是完成了任务。因此,这些信号应当不一样。
因此,给每一种中断编一个号码,以此来标识它的唯一性就是一个很好的解决办,这个号码就是中断号,或者叫做中断向量,或者中断类型号。
前面说过,中断是用来改变CPU执行状态的,中断传进来就应该让CPU执行别的程序,这个别的程序就是中断处理程序,顾名思义,就是用中断处理程序来看一下为什么要传送一个中断给CPU。
通常,操作系统维护一个指针数组,称为中断向量表,以不同的中断号作为索引可以找到其对应的中断处理程序。
Intel处理器允许有256个中断号,0~255。
3.双重模式
在讲内中断前先讲一下双重模式,即操作系统执行有两种模式,用户模式和内核模式(或者叫做特权模式,系统模式)。
为什么会存在双重模式这种东西
对于单道程序系统,一次只执行一个程序,想怎么执行怎么执行。但是对于多道程序系统,多个程序是并发执行的,这就出现了问题。如果其中一个程序出现了错误,很有可能影响到别的程序。或者一个程序执行时,它去修改了另一个程序,导致别的程序执行错误。操作系统的存在就为了程序能够有效安全正确的执行,操作系统要去管理这些程序按照正确的轨迹执行,那它就要比别的程序的级别高,它能做一些别的程序不能做到的事情,它是有特权的。操作系统的特权包括I/O控制,定时器管理,中断管理等。
这就是双重模式,普通的用户程序在用户模式下执行,操作系统在内核模式下执行。
但是又出现了问题,用户程序有时也需要特权,比如它需要用到I/O设备。但是操作系统又不能赋予用户程序某种特权,因为用户程序有了和操作系统一样的特权后就不受到操作系统的管控了,显然不能这样做。因此,有了一种折中的方案,用户普通程序告诉内核它想完成的事情,内核经过决断后帮它完成这件事或者不允许它做这件事。
内核帮助用户程序执行特权任务就需要CPU从用户程序转到内核程序,同时也从用户态转到内核态。
用户程序是怎么通知内核它要执行什么特权的呢
答案是软中断。
4.软中断
软中断是内中断,也叫做陷阱(trap)。就是用户程序故意发送一个中断信号给CPU,让CPU转到内核态执行,以这种方式让内核替用户程序完成某些特权操作。比如退出程序,读用户输入,显示东西到屏幕等。
软中断有一个统一的中断号0x80,执行int 0x80时,程序会转到内核执行相应的特权操作,这称为系统调用。通常,eax中存放一个编号,内核根据这个编号得知用户程序想要执行的是具体哪种特权操作。
5.定时器
考虑这样一种情况,某个用户程序中有一个无限循环,比如
int i=0;
while(1)
{
i++;
}
这个程序将会一直执行,它不需要系统调用,也不会引起硬件中断,它不会转到内核执行,因此控制权一直在用户程序手里。但是任由它无休止的执行下去,它将永远占用CPU资源,这实际上是没有意义的。
因此,操作系统使用一个叫做定时器的东西来避免这种情况。可以设置定时器在指定周期(固定的或者可变的)后引发一个中断,通过这个中断让用户程序转到内核执行,内核判断用户程序是否还需要继续执行。这就解决了用户程序一直执行不将控制给内核的情况。