CPU虚拟化-机制:受限直接执行
2023-1-9
| 2023-8-2
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property
 
 
构建虚拟化时存在一些挑战:
  • 性能:如何在不增加系统开销的情况下实现虚拟化?
  • 控制权:如何有效地运行进程,同时保留对 CPU 的控制?
 
操作系统必须以高性能的方式虚拟化CPU,同时保持对系统的控制。为此,需要硬件和操作系统支持。操作系统通常会明智地利用硬件支持,以便高效地实现其工作。
 

策略:直接执行

只需直接在CPU上运行程序即可。
OS 希望启动程序运行时,它会在进程列表中为其创建一个进程条目,为其分配一些内存,将程序代码(从磁盘)加载到内存中,找到入口点(main()函数或类似的),跳转到那里,并开始运行用户的代码。
notion image
这种方法会产生一些问题:
  • 受限制的操作:操作系统怎么能确保程序不做任何我们不希望它做的事,同时仍然高效地运行它?
  • 进程间切换: 操作系统如何让一个进程停下来并切换到另一个进程,从而实现虚拟化CPU所需的时分共享
 

策略:受限直接执行

需要解决两个问题:
  1. 限制进程可以执行的指令
    1. 采用受保护的控制权转移:硬件通过提供不同的执行模式来协助操作系统。
      • 用户模式(user mode)下,应用程序不能完全访问硬件资源。例如,在用户模式下运行时,进程不能发出I/O请求。
      • 内核模式(kernel mode)下,操作系统可以访问机器的全部资源。
       
      如果用户希望执行某种特权操作(如从磁盘读取),应该怎么做?
      为了实现这一点,几乎所有的现代硬件都提供了用户程序执行系统调用的能力,允许内核小心地向用户程序暴露某些关键功能,例如访问文件系统、创建和销毁进程、与其他进程通信,以及分配更多内存。
      要执行系统调用,程序必须执行特殊的陷入(trap)指令,该指令同时跳入内核并将特权级别提升到内核模式。一旦进入内核,系统就可以执行任何需要的特权操作(如果允许),从而为调用进程执行所需的工作。完成后,操作系统调用一个特殊的从陷阱返回(return-from-trap)指令,返回到发起调用的用户程序中,同时将特权级别降低,回到用户模式。
       
      陷阱如何知道在OS 内运行哪些代码?
      内核通过在启动时设置陷阱表(trap table)来实现。当机器启动时,它在特权(内核)模式下执行,因此可以根据需要自由配置机器硬件。操作系统做的第一件事,就是告诉硬件在发生某些异常事件时要运行哪些代码。例如,当发生硬盘中断,发生键盘中断或程序进行系统调用时,应该运行哪些代码?操作系统通常通过某种特殊的指令,通知硬件这些陷阱处理程序的位置。一旦硬件被通知,它就会记住这些处理程序的位置,直到下一次重新启动机器,并且硬件知道在发生系统调用和其他异常事件时要做什么(即跳转到哪段代码)。
       
      受限直接运行协议:
      notion image
      LDE 协议有两个阶段。第一个阶段(在系统引导时),内核初始化陷阱表,并且CPU记住它的位置以供随后使用。内核通过特权指令来执行此操作(所有特权指令均以粗体突出显示)。第二个阶段(运行进程时),在使用从陷阱返回指令开始执行进程之前,内核设置了一些内容(例如,在进程列表中分配一个节点,分配内存)。这会将CPU切换到用户模式并开始运行该进程。当进程希望发出系统调用时,它会重新陷入操作系统,然后再次通过从陷阱返回,将控制权还给进程。该进程然后完成它的工作,并从main()返回。这通常会返回到一些存根代码,它将正确退出该程序(例如,通过调用exit()系统调用,这将陷入OS 中)。此时,OS清理干净,任务完成了。
  1. 在进程之间切换
    1. 操作系统如何重新获得CPU 的控制权,以便它可以在进程之间切换?
      • 协作方式:等待系统调用 过去某些系统采用协作方式。在这种风格下,操作系统相信系统的进程会合理运行。运行时间过长的进程被假定会定期放弃CPU,以便操作系统可以决定运行其他任务。
        • 在协作调度系统中,OS 通过等待系统调用,或某种非法操作发生,从而重新获得 CPU 的控制权。
      • 非协作方式:时钟中断 时钟设备可以编程为每隔几毫秒产生一次中断。产生中断时,当前正在运行的进程停止,操作系统中预先配置的中断处理程序(interrupt handler)会运行。此时,操作系统重新获得 CPU 的控制权,因此可以做它想做的事:停止当前进程,并启动另一个进程。
        •  
          操作系统必须通知硬件哪些代码在发生时钟中断时运行。因此,在启动时,操作系统就是这样做的。其次,在启动过程中,操作系统也必须启动时钟,这当然是一项特权操作。一旦时钟开始运行,操作系统就感到安全了,因为控制权最终会归还给它,因此操作系统可以自由运行用户程序。时钟也可以关闭
          硬件在发生中断时有一定的责任,尤其是在中断发生时,要为正在运行的程序保存足够的状态,以便随后从陷阱返回指令能够正确恢复正在运行的程序。这一组操作与硬件在显式系统调用陷入内核时的行为非常相似,其中各种寄存器因此被保存(进入内核栈),因此从陷阱返回指令可以容易地恢复。
      • 保存和恢复上下文 当操作系统通过上述两种方式获取控制权后,就可以决定:是继续运行当前正在运行的进程,还是切换到另一个进程,这个决定是由调度程序(scheduler)做出。
        • 当操作系统决定切换进程时,需要首先进行上下文切换(context switch),就是为当前正在执行的进程保存一些寄存器的值(例如,到它的内核栈),并为即将执行的进程恢复一些寄存器的值(从它的内核栈)。这样一来,操作系统就可以确保最后执行从陷阱返回指令时,不是返回到之前运行的进程,而是继续执行另一个进程。
           
      进程A 正在运行,然后被中断时钟中断。硬件保存它的寄存器(在内核栈中),并进入内核(切换到内核模式)。在时钟中断处理程序中,操作系统决定从正在运行的进程A 切换到进程B。此时,它调用switch()例程,保存当前寄存器的值(保存到A 的进程结构),恢复寄存器进程B(从它的进程结构),然后切换上下文(switch context),具体来说是通过改变栈指针来使用B 的内核栈(而不是A 的)。最后,操作系统从陷阱返回,恢复B 的寄存器并开始运行它。
      notion image
 
 
  • 计算机基础
  • 操作系统
  • CPU虚拟化-进程CPU虚拟化-进程调度
    目录