机制:受限直接执行(原书第六章)
时分共享技术带来的两个挑战
- 性能问题即 :在不增加系统开销的情况下实现虚拟化
- 控制权问题,如何有效的运行进程同时保留对CPU的控制
因此这里的目标就是:操作系统必须以高性能的方式虚拟化CPU,同时保持对系统的控制
基本技巧:受限直接执行
前面介绍过,操作系统在运行程序时的一些基本步骤,就是加载到内存、堆栈内存分配,IO初始化等等这些步骤,在程序真正作为进程跑起来的时候,我们需要对其进行一定的管控,比如:对于一些敏感行为不允许它操作、在需要进程切换的时候能够能够让当前进程停下来切换到其他进程去执行。
这种方式就带来了两个问题:
问题1:受限操作
这里针对受限的控制,引入了【内核模式】和【用户模式】的概念:
- 用户模式是一种受限的模式,比如程序在用户模式下是无法进行IO调用的,一旦强行越界发出IO请求,操作系统可能会终止进程。
- 在内核模式下,权限全开,操作系统就是运行在这种模式下的,此模式下运行的代码可以做它任何想做的,甚至是特权操作。
在这种用户模式和内核模式的配合下,内核适当开放一部分关键功能,比如:访问文件、进程创建和销毁等,在此基础上如果用户模式下的程序需要执行这些系统调用,就会执行一个特殊的【陷阱】指令,该指令会同时跳入内核并将特权级别调整为内核模式。
在系统调用执行完成后,再调用一个特殊的从陷阱返回指令(return-from-trap)。此时将返回到发起调用的用户程序中,并将特权级别调整为用户模拟。
所以这里进入trap时,硬件需要保证将所有必要的信息存储到寄存器中,以便于从陷阱指令返回后能够正常执行。
随之带来的另一个问题就是:如何知道陷阱对应的代码在什么地方?
触发陷阱的时候,肯定不是先进入到内核中然后再检查,这样存在很大的安全隐患(狡猾的程序员可能会绕过一些检测,此时就直接在内核模式操作了)。因此需要先检查再确定触发陷阱进入内核模式。
对应的解决方案就是:内核在启动的时候,会设置陷阱表,因为在机器启动的时候,此时处于内核模式,可以根据需要配置所需的硬件资源,此时操作系统要做的第一件事就是告诉硬件在触发某些异常陷阱时,需要到哪里去执行指定的代码。
这里的【告诉硬件在触发陷阱时该执行什么代码】这个指令非常强大,所以它本身就是一个特权操作。所以如果强制在用户模式下执行该指令,硬件直接拒绝。
问题2:在进程之间进行切换
这里的关键问题就是:如何使操作系统重新获得CPU的控制权。因为进程本身就在CPU上正在跑着,需要把它扒下来。
- 协作方式:等待系统调用
早期的Macintosh就是采用这种协作的方式,这种方式是基于一个友好的假定前提:那就是进程本身会自动释放CPU,或者运行时间很长的进程会定期释放CPU控制权;此时进程如果进行了一些不当的操作依旧会将控制权交还给OS。可以看到这种假设很明显带有极端的乐观精神,现实很复杂,如果遇到那种狡猾的程序员或者是那种充满缺陷的程序,不断进入了死循环,就导致CPU永远被它占用了。
- 非协作方式:操作系统进行控制
基于前面一种协作方式存在的问题,现行的一种方式就是主动进行控制,那就是引入一种【时钟中断】,时钟设备每隔一段时间会进行一次中断操作,中断时,停止当前正在运行的进程,转而去运行操作系统事先配置好的中断处理程序,此时操作系统就能重新获取CPU的控制权了;所以这里操作系统需要在计算机启动时就预先指定好中断处理程序,并且在机器启动时也要自动启动时钟设备,这样才能保证无论如何,最终的CPU控制权都会回到OS身上。
- 保存和恢复上下文
前面提到的时钟中断问题,需要考虑中断时的现场保存问题,以便于在进程在从陷阱中返回执行的时候可以正常续接上之前未完成的工作,这个和前面介绍到的显式调用硬件陷入陷阱是类似的情况,因此需要各种寄存器来保存现场信息。
那么还有一个问题:如果在中断处理过程中又发生了中断,这种该如何处理?
当然最简单的方案就是时,在中断发生时,不允许再发生中断,当然这样做需要额外小心,因为如果时间过长有可能导致中断丢失。实际情况可能更加复杂,这里暂时不做深入追究,等后续章节介绍时,涉及到了自然再进行深入探究。
标签:02,操作系统,中断,导论,模式,内核,进程,CPU From: https://www.cnblogs.com/StillLoving/p/limited-direct-execution.html