03:CPU如何保证自己的控制权不被进程抢占?

  通过运行一个进程一段时间,然后运行另一个进程,如此反复切换,以这种方式时分共享CPU实现了虚拟化。但构建这样的虚拟化机制时存在一些挑战。

  1. 第一个就是性能,如果在不增加系统的开销情况下实现虚拟化?
  2. 第二个就是控制权,如何有效运行进程,同时保留对CPU的控制?

  控制权对于操作系统尤为重要,因为操作系统作为物理资源的大管家,如果没有控制权,一个进程就可以随便地接手物理资源的支配,如果这个进程的某些行为想要干扰其他进程那将不可想象。因此保持操作系统的控制权并且同时获得高性能是构建操作系统的主要挑战之一。

  为了解决这两个问题,使程序尽可能快地运行,操作系统开发人员相处了一个技术——受限直接执行

  当操作系统希望启动程序运行时,它会在进程列表中为程序创建一个进程条目,为它分配一些内存,将程序代码从磁盘加载到内存中,找到main函数并跳转到哪里,开始执行程序代码。当程序执行完成,操作系统释放进程的内存,将进程从进程列表中删除。这个方法在虚拟化CPU时会产生一些问题。

  1. 第一个问题:如果我们只运行一个程序,那么操作系统怎么能确保程序不做任何我们不希望它做的事?同时仍能够高效地运行?
  2. 第二个问题:当我们运行一个进程时,操作系统如何让它停下来并切换到另一个进程,从而实现虚拟化CPU所需的时分共享?

  针对第一个问题,如果进程希望执行某种受限的操作,比如希望请求CPU给更多的内存,CPU该不该受理?针对这类问题,我们采用的方法是通过硬件提供两种不同的执行模式来协助操作系统把控控制权,第一种称为用户模式。在用户模式下运行的代码会受到限制,比如用户模式下运行的程序,进程不能发出I/O请求或者申请内存,这样做会避免CPU引发异常,导致操作系统可能会终止该进程。

  与用户模式相对应的是内核(操作系统)模式,操作系统就是以这种模式运行的。在内核模式下,进程可以做它喜欢的事,包括特权操作,比如发出I/O请求或者是请求内存等。

  但是我们依然面临一个挑战,如果用户希望执行某种特权操作,比如说申请内存,为了实现这一点,现代硬件提供了用户程序执行系统调用的能力。这种能力允许内核向用户程序暴漏某些关键功能,比如访问文件系统、创建和销毁进程、与其他进程通信、分配更多的内存。

  要执行系统调用,程序必须执行特殊的陷阱指令,陷阱指令可以将特权级别提升到内核模式。只要进入了内核模式,系统就可以执行任何需要的特权操作。完成后,操作系统调用一个特殊的陷阱返回指令,这个指令会返回到发起系统调用的用户程序中,同时将特权级别降低,回到用户模式。

  程序申请内存 ——> 程序执行系统调用 ——> 执行陷阱指令将特权级别提升到内核模式 ——> 申请内存 ——> 操作系统执行陷阱返回指令 ——> 陷阱返回指令返回到程序中 ——> 操作系统将特权级别降低到用户模式

  执行陷阱时,CPU会将程序计数器、标志和一些寄存器推送到每个进程的内核栈,当返回陷阱从栈弹出这些值时,恢复执行用户模式程序。

  还有一个重要的细节,陷阱是如何知道在操作系统内运行哪些代码?发起调用的过程不能指定要跳转到的地址,如果程序可以跳转到内核中任意位置,那么可能会导致程序在内核中运行任意代码,抢夺控制权。因此内核必须谨慎地控制陷阱上执行的代码。可以给权限,但不能越界。

  操作系统内核是通过在启动时设置陷阱表来实现。当机器启动时,操作系统做的第一件事,就是告诉硬件在发生某些异常事件时要运行哪些代码。操作系统通过某种特殊的指令通知硬件这些陷阱处理程序的位置。一旦硬件被通知,它就会记住这些处理程序的位置,直到下一次重新启动机器,并且硬件知道在发生系统调用和其他异常事件时要跳转到哪段代码。能够执行指令告诉硬件陷阱表的位置是一个非常强大的功能。这也是一个特权操作。

  1.   操作系统启动内核模式并初始化陷阱表(内核模式)
  2.   记住系统调用处理程序的地址(硬件)
  3.   操作系统运行内核模式 ——> 在进程列表中创建进程条目 ——> 为程序分配内存 ——> 将程序从磁盘加载到内存 ——> 用寄存器和程序计数器填充内核栈 ——> 从陷阱返回(内核模式)
  4.   通过硬件从内核栈恢复寄存器 ——> 硬件转向用户模式 ——> 硬件跳转到main函数(硬件)
  5.   运行main函数 ——> 调用系统调用 ——> 陷入操作系统(用户模式)
  6.   将寄存器保存到内核栈 ——> 硬件转向内核模式 ——> 硬件跳到陷阱处理程序 (硬件)
  7.   操作系统处理陷阱 ——> 操作系统做系统调用的工作 ——> 从陷阱返回 (内核模式)
  8.   从内核栈恢复寄存去 ——> 转向用户模式 ——> 跳到陷阱之后的程序计数器(硬件)
  9.   程序从main返回 ——> 通过exit退出程序(用户模式)
  10.   操作系统释放进程的内存 ——> 将进程从进程列表中删除(内核模式)

  

  受限制直接运行协议,简称为LDE协议,LDE协议有两个阶段,第一个阶段就是在系统引导时,内核初始化陷阱表,并且CPU记住它的位置以供后续使用。内核通过特权指令执行此操作。第二个阶段是在运行进程时,在使用从陷阱返回指令开始执行进程之前,内核设置了一些容,在进程列表中分配一个节点,分配内存。这回将CPOU切换到用户模式并开始运行该进程。当进程希望发出系统调用时,它会重新陷入操作系统,然后再次通过从陷阱返回,将控制权还给进程。当进程完成它的工作并从main函数返回,这通常会返回到一些存根代码,它将正确推出程序,如通过调用exit函数系统调用,将再次陷入操作系统中,此时操作系统清理进程,任务完成。

  最后总结下第一个问题,为了保证程序请求CPU执行受限制的指令时,CPU可以保持控制权,通过设立两种不同权限解决程序和CPU的控制权问题,即LDE协议。如果一个程序想要进行特权操作,需要通过系统调用执行陷阱指令才能进入内核模式,当执行完特权操作后,操作系统会调用陷阱返回指令,将程序的特权级别恢复到用户模式。

  

 

  

  

posted @ 2020-08-22 04:32  我的偶像是木子  阅读(684)  评论(0)    收藏  举报