重学操作系统(十二)
前言
之前提到了用户态进行系统调用会有一个中断的操作(Trap)。今天就来看下中断到底是什么。
在此之前,我们可以回想下。我们每天都会和键盘,鼠标这种外设有互动。可是,Java等语言是怎么捕获到键盘的输入的呢?后面会先讲一下响应这些外设的一个设计思想,以键盘为例,后面引出中断相关的知识点。
贯穿全文的一道题:Java/js 等语言为什么可以捕获到键盘输入?
*** 设计响应键盘
设计目标
在Java等语言中实现按键响应,类似Switch-Case,根据不同按键执行不同功能。
按键抽象
按键一般不会超过128个,因此可以用Byte数据描述用户按键。按键一般分为按下和释放两个状态。对于一个Byte类型的数,最高位可以用来表示状态,后7位(0 - 127)表示具体按键。
处理按键
可以由操作系统做一部分处理后交给程序处理:
例如用户按下回车键,先由操作系统统一封装,再把按键的编码转换成字符串Enter方便各种程序使用
处理组合键,操作系统先一步计算比较好,因为底层只知道按键的释放和按下状态。组合键必须结合时间因素判断。
响应按键
当一个Java或者其它语言写的应用程序要响应按键时,一般用消息模型。如果程序不停扫描按键,会造成系统很大的负担。如果程序在操作系统注册一个响应按键的函数,每次只有触发按键才执行,就能减少开销。
按键操作
这里就要用到中断了,一般来说,按键是高优先级的操作,因此如果有按键操作,一般要中断先有操作去响应。这就需要硬件层面的支持了。因此也才会涉及到中断的概念。
识别按键
每次按键,通过总线(Bus)通知CPU,CPU中断正在执行的程序,然后切换执行按键相关的程序。CPU切换执行程序的办法是改变PC指针。这样的好处是,降低CPU和按键的耦合性,让CPU在日常情况下,能专注高效的处理指令。
其中一个设计思想是:
我们只能控制CPU跳转到固定位置,比如CPU一收到主板信息(比如按键操作),CPU会马上中断当前程序,将PC指针设置为0。所有操作的最新指令都放在内存为0的地址中。
主板识别
关于主板如何识别按键,其中设计思路为:
可以将按键信息转换成具体的按键值,比如用户按下A,A在第几行第几咧,可以看作一个电信号。然后把这个电信号转化成一个Byte型数字。转换完成,主板就可以接收到这个数字(按键码),然后写入寄存器,通知CPU
中断设计
经过上面几步,整体设计分为了三层,第一层是硬件设计,然后是操作系统设计,接着是程序语言设计。
按键码的收集,是键盘芯片和主板的能力。主板知道有新的按键后,通知CPU,CPU要中断当前执行的程序,将PC指针跳转到一个固定位置,这便是一次 中断。
我们需要根据中断类型来判断PC指针跳转的位置,中断类型不同,PC指针跳转位置也可能不同。比如按键程序,打印机,系统异常,包括系统调用等都需要中断操作。
这种分类叫作中断识别码。不同的中断发生时,CPU需要知道PC指针该跳转到哪个地址,这个地址称为中断向量(Interupt Vector)。存储中断向量的内存空间,叫作中断向量表。
因此,按键按下的整个接收信号流程可以是:
- 按键按下,通过消息传递方式,将消息传递给CPU。
- CPU收到信号后,进入中断,并根据中断类型,操作PC指针,找到中断向量。操作系统会插入一条指令,将PC指针跳转到对应中断的处理程序。
- 上述结束后,操作系统便接管了后续处理。按键信号被放入一个队列,保存下来。因为操作系统不一定能保证及时处理所有按键。
- 对于组合按键,可以利用按下、释放之间的时间关系。
- 经过计算将按键抽象成信息。
- 提供API给应用程序,让应用程序可以监听操作系统处理后的信息。
- 分发按键消息给监听按键的程序。
中断类型
按触发方式
- 同步中断
中断可以由CPU指令直接触发。有以下几种情况:
- 系统调用,从用户态转到内核态,触发中断,叫作Trap,中断触发后,需要继续执行系统调用。
- 另一种同步中断情况是错误(Fault),通常是因为检测到某种错误,需要触发一个中断。中断响应结束后,会重新执行触发错误的地方。
- 最后一种情况是程序的异常,类似Trap,用于实现程序抛出的异常。
- 异步中断
异步中断不是由CPU直接触发,是因为需要响应外部的通知,比如响应键盘,鼠标等设备而触发的中断。
根据中断是否潜质触发
- 可屏蔽中断
CPU通常都支持设置一个中断屏蔽位(一个寄存器),设置为1后,CPU暂时就不再响应中断。对于键盘鼠标输入,比如Trap,错误,异常等情况,会被临时屏蔽。但是对于类似CPU故障导致的掉电中断,还是会正常触发。可以被屏蔽的中断称为可屏蔽中断,大部分中断是可屏蔽中断。
- 不可屏蔽中断
类似CPU故障导致的掉电中断这种严重的问题是不可屏蔽中断
总结
因此,回到前面的问题,应该能有一个比较抽象的答案了:
为了捕获到键盘输入,硬件层需要把按键抽象为中断,中断CPU执行。CPU根据中断类型(中断识别码),找到对应的中断向量(内存地址)。操作系统预置了中断向量,因此发生中断后,操作系统接管了程序。操作系统实现了解析按键的基本算法,将按键抽象为键盘时间,并且提供队列存储多个按键,还提供了监听的API。因此例如Java等语言的程序,就可以通过调用系统API使用按键事件。
Q:操作系统可以处理键盘按键,这很好理解,但是在开机的时候系统还没有载入内存,为什么可以使用键盘呢?这个怎么解释?
A:主板上有一块ROM上有一个简化操作系统,叫作BIOS(Basic Input/Output System),在开机没有进入操作系统期间,BIOS来管理机器,并且协助加载OS到内存。现代OS在加载进入内存后,会替换掉BIOS的中断向量。
参考
[1] https://kaiwu.lagou.com/course/courseInfo.htm?courseId=478#/detail/pc?id=4622