《操作系统导论》知识总结 第六章 机制:受限直接执行

在四章中已经知道,要实现 CPU 的虚拟化,操作系统就需要一些低级机制以及一些高级智能

我们将低级机制称为机制(mechanism)。机制是一些低级方法协议,实现了所需的功能。

这一章我们介绍一种机制:受限直接执行

构建虚拟化时存在一些挑战:

  • 性能:如何在不增加系统开销的情况下实现虚拟化?
  • 控制权:如何有效地运行进程,同时保留对 CPU 的控制?

控制权对于操作系统尤为重要,因为操作系统负责资源管理。如果没有控制权,一个进程可以简单地无限制运行并接管机器,或访问没有权限的信息

直接运行协议

这个概念的“直接执行”部分很简单:只需直接在 CPU上运行程序即可。
下表展示了这种直接运行协议:
在这里插入图片描述
当 OS 希望启动程序运行时,它会在进程列表中为其创建一个进程条目,为其分配一些内存,将程序代码(从磁盘)加载到内存中,找到入口点(main()函数或类似的),跳转到那里,并开始运行用户的代码。

这种方法会产生一些问题:

  • 受限制的操作:操作系统怎么能确保程序不做任何我们不希望它做的事,同时仍然高效地运行它?
  • 进程间切换: 操作系统如何让一个进程停下来并切换到另一个进程,从而实现虚拟化 CPU 所需的时分共享

问题 1:受限制的操作

采用受保护的控制权转移

硬件通过提供不同的执行模式来协助操作系统。在用户模式user mode)下,应用程序不能完全访问硬件资源。在内核模式kernel mode)下,操作系统可以访问机器的全部资源。还提供了陷入trap内核从陷阱返回return-from-trap)到用户模式程序的特别说明,以及一些指令,让操作系统告诉硬件陷阱表trap table)在内存中的位置。

我们采用的方法是引入新的处理器模式:用户模式(user mode):在用户模式下运行的代码会受到限制。例如,在用户模式下运行时,进程不能发出 I/O 请求。这样做会导致处理器引发异常,操作系统可能会终止进程。

与用户模式不同的是内核模式(kernel mode):操作系统(或内核)就以这种模式运行。在此模式下,运行的代码可以做它喜欢的事,包括特权操作,如发出 I/O 请求和执行所有类型的受限指令。

几乎所有的现代硬件都提供了用户程序执行系统调用的能力,从而使用户执行某种特权操作(如从磁盘读取)。

系统调用:允许内核小心地向用户程序暴露某些关键功能,例如访问文件系统、创建和销毁进程、与其他进程通信,以及分配更多内存

要执行系统调用,程序必须执行特殊的陷阱(trap)指令。该指令同时跳入内核并将特权级别提升到内核模式。一旦进入内核,系统就可以执行任何需要的特权操作(如果允许),从而为调用进程执行所需的工作。完成后,操作系统调用一个特殊的从陷阱返回(return-from-trap)指令,如你期望的那样,该指令返回到发起调用的用户程序中,同时将特权级别降低回到用户模式

执行陷阱时,硬件需要小心,因为它必须确保存储足够的调用者寄存器,以便在操作系统发出从陷阱返回指令时能够正确返回。例如,在 x86 上,处理器会将程序计数器、标志和其他一些寄存器推送到每个进程的内核栈(kernel stack)上。从返回陷阱将从栈弹出这些值,并恢复执行用户模式程序。

内核通过在启动时设置陷阱表trap table)来实现如何知道在 OS 内运行哪些代码。

当机器启动时,系统在特权(内核)模式下执行,因此可以根据需要自由配置机器硬件。操作系统做的第一件事,就是告诉硬件在发生某些异常事件时要运行哪些代码。例如,当发生硬盘中断,发生键盘中断或程序进行系统调用时,应该运行哪些代码?操作系统通常通过某种特殊的指令,通知硬件这些陷阱处理程序的位置。一旦硬件被通知,它就会记住这些处理程序的位置直到下一次重新启动机器并且硬件知道在发生系统调用和其他异常事件时要做什么(即跳转到哪段代码)。

受限直接运行协议

LDE 协议有两个阶段:

在这里插入图片描述
第一个阶段(在系统引导时),内核初始化陷阱表,并且 CPU 记住它的位置以供随后使用。内核通过特权指令来执行此操作(所有特权指令均以粗体突出显示)。
在这里插入图片描述
第二个阶段(运行进程时),在使用从陷阱返回指令开始执行进程之前,内核设置了一些内容(例如,在进程列表中分配一个节点,分配内存)。这会将 CPU 切换到用户模式并开始运行该进程。当进程希望发出系统调用时,它会重新陷入操作系统,然后再次通过从陷阱返回,将控制权还给进程。该进程然后完成它的工作,并从 main()返回。这通常会返回到一些存根代码,它将正确退出该程序(例如,通过调用 exit()系统调用,这将陷入 OS 中)。此时,OS 清理干净,任务完成了。

问题 2:在进程之间切换

关键问题:如何重获 CPU 的控制权
操作系统如何重新获得 CPU 的控制权(regain control),以便它可以在进程之间切换?

协作方式:等待系统调用

过去某些系统采用协作方式。在这种风格下,操作系统相信系统的进程会合理运行。运行时间过长的进程被假定会定期放弃CPU,以便操作系统可以决定运行其他任务。

在协作调度系统中,OS 通过等待系统调用,或某种非法操作发生,从而重新获得 CPU 的控制权。

非协作方式:时钟中断

时钟设备可以编程为每隔几毫秒产生一次中断。产生中断时,当前正在运行的进程停止,操作系统中预先配置的中断处理程序(interrupt handler)会运行。此时,操作系统重新获得 CPU 的控制权,因此可以做它想做的事:停止当前进程,并启动另一个进程。

硬件在发生中断时有一定的责任,尤其是在中断发生时,要为正在运行的程序保存足够的状态,以便随后从陷阱返回指令能够正确恢复正在运行的程序。这一组操作与硬件在显式系统调用陷入内核时的行为非常相似,其中各种寄存器因此被保存(进入内核栈),因此从陷阱返回指令可以容易地恢复。

保存和恢复上下文

当操作系统通过上述两种方式获取控制权后,就可以决定是否切换进程,这个决定是由调度程序(scheduler)做出。

当操作系统决定切换进程时,需要首先进行上下文切换(context switch),就是为当前正在执行的进程保存一些寄存器的值(例如,到它的内核栈),并为即将执行的进程恢复一些寄存器的值(从它的内核栈)。这样一来,操作系统就可以确保最后执行从陷阱返回指令时,不是返回到之前运行的进程,而是继续执行另一个进程。

下图展示受限直接执行协议(时钟中断):
在这里插入图片描述

进程 A 正在运行,然后被中断时钟中断。硬件保存它的寄存器(在内核栈中),并进入内核(切换到内核模式)。在时钟中断处理程序中,操作系统决定从正在运行的进程 A 切换到进程 B。此时,它调用 switch()例程,该例程仔细保存当前寄存器的值(保存到 A 的进程结构),恢复寄存器进程 B(从它的进程结构),然后切换上下文(switch context),具体来说是通过改变栈指针来使用 B 的内核栈(而不是 A 的)。最后,操作系统从陷阱返回,恢复 B 的寄存器并开始运行它。

在此协议中,有两种类型的寄存器保存/恢复。第一种是发生时钟中断的时候。在这种情况下,运行进程的用户寄存器由硬件隐式保存,使用该进程的内核栈。第二种是当操作系统决定从 A 切换到 B。(期中考试考过)
这篇文章比较详细介绍了这两种寄存器保存/恢复

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值