MIT6.S081
  • 简介
  • Lec01 Introduction and Examples (Robert)
    • 1.1 课程内容简介
    • 1.2 操作系统结构
    • 1.3 Why Hard and Interesting
    • 1.4 课程结构和资源
    • 1.5 read, write, exit系统调用
    • 1.6 open系统调用
    • 1.7 Shell
    • 1.8 fork系统调用
    • 1.9 exec, wait系统调用
    • 1.10 I/O Redirect
  • Lec03 OS Organization and System Calls (Frans)
    • 3.1 上一节课回顾
    • 3.2 操作系统隔离性(isolation)
    • 3.3 操作系统防御性(Defensive)
    • 3.4 硬件对于强隔离的支持
    • 3.5 User/Kernel mode切换
    • 3.6 宏内核 vs 微内核 (Monolithic Kernel vs Micro Kernel)
    • 3.7 编译运行kernel
    • 3.8 QEMU
    • 3.9 XV6 启动过程
  • Lec04 Page tables (Frans)
    • 4.1 课程内容简介
    • 4.2 地址空间(Address Spaces)
    • 4.3 页表(Page Table)
    • 4.4 页表缓存(Translation Lookaside Buffer)
    • 4.5 Kernel Page Table
    • 4.6 kvminit 函数
    • 4.7 kvminithart 函数
    • 4.8 walk 函数
  • Lec05 Calling conventions and stack frames RISC-V (TA)
    • 5.1 C程序到汇编程序的转换
    • 5.2 RISC-V vs x86
    • 5.3 gdb和汇编代码执行
    • 5.4 RISC-V寄存器
    • 5.5 Stack
    • 5.6 Struct
  • Lec06 Isolation & system call entry/exit (Robert)
    • 6.1 Trap机制
    • 6.2 Trap代码执行流程
    • 6.3 ECALL指令之前的状态
    • 6.4 ECALL指令之后的状态
    • 6.5 uservec函数
    • 6.6 usertrap函数
    • 6.7 usertrapret函数
    • 6.8 userret函数
  • Lec08 Page faults (Frans)
    • 8.1 Page Fault Basics
    • 8.2 Lazy page allocation
    • 8.3 Zero Fill On Demand
    • 8.4 Copy On Write Fork
    • 8.5 Demand Paging
    • 8.6 Memory Mapped Files
  • Lec09 Interrupts (Frans)
    • 9.1 真实操作系统内存使用情况
    • 9.2 Interrupt硬件部分
    • 9.3 设备驱动概述
    • 9.4 在XV6中设置中断
    • 9.5 UART驱动的top部分
    • 9.6 UART驱动的bottom部分
    • 9.7 Interrupt相关的并发
    • 9.8 UART读取键盘输入
    • 9.9 Interrupt的演进
  • Lec10 Multiprocessors and locking (Frans)
    • 10.1 为什么要使用锁?
    • 10.2 锁如何避免race condition?
    • 10.3 什么时候使用锁?
    • 10.4 锁的特性和死锁
    • 10.5 锁与性能
    • 10.6 XV6中UART模块对于锁的使用
    • 10.7 自旋锁(Spin lock)的实现(一)
    • 10.8 自旋锁(Spin lock)的实现(二)
  • Lec11 Thread switching (Robert)
    • 11.1 线程(Thread)概述
    • 11.2 XV6线程调度
    • 11.3 XV6线程切换(一)
    • 11.4 XV6线程切换(二)
    • 11.5 XV6进程切换示例程序
    • 11.6 XV6线程切换 --- yield/sched函数
    • 11.7 XV6线程切换 --- switch函数
    • 11.8 XV6线程切换 --- scheduler函数
    • 11.9 XV6线程第一次调用switch函数
  • Lec13 Sleep & Wake up (Robert)
    • 13.1 线程切换过程中锁的限制
    • 13.2 Sleep&Wakeup 接口
    • 13.3 Lost wakeup
    • 13.4 如何避免Lost wakeup
    • 13.5 Pipe中的sleep和wakeup
    • 13.6 exit系统调用
    • 13.7 wait系统调用
    • 13.8 kill系统调用
  • Lec14 File systems (Frans)
    • 14.1 Why Interesting
    • 14.2 File system实现概述
    • 14.3 How file system uses disk
    • 14.4 inode
    • 14.5 File system工作示例
    • 14.6 XV6创建inode代码展示
    • 14.7 Sleep Lock
  • Lec15 Crash recovery (Frans)
    • 15.1 File system crash概述
    • 15.2 File system crash示例
    • 15.3 File system logging
    • 15.4 log_write函数
    • 15.5 end_op函数
    • 15.6 File system recovering
    • 15.7 Log写磁盘流程
    • 15.8 File system challenges
  • Lec16 File system performance and fast crash recovery (Robert)
    • 16.1 Why logging
    • 16.2 XV6 File system logging回顾
    • 16.3 ext3 file system log format
    • 16.4 ext3如何提升性能
    • 16.5 ext3文件系统调用格式
    • 16.6 ext3 transaction commit步骤
    • 16.7 ext3 file system恢复过程
    • 16.8 为什么新transaction需要等前一个transaction中系统调用执行完成
    • 16.9 总结
  • Lec17 Virtual memory for applications (Frans)
    • 17.1 应用程序使用虚拟内存所需要的特性
    • 17.2 支持应用程序使用虚拟内存的系统调用
    • 17.3 虚拟内存系统如何支持用户应用程序
    • 17.4 构建大的缓存表
    • 17.5 Baker's Real-Time Copying Garbage Collector
    • 17.6 使用虚拟内存特性的GC
    • 17.7 使用虚拟内存特性的GC代码展示
  • Lec18 OS organization (Robert)
    • 18.1 Monolithic kernel
    • 18.2 Micro kernel
    • 18.3 Why micro kernel?
    • 18.4 L4 micro kernel
    • 18.5 Improving IPC by Kernel Design
    • 18.6 Run Linux on top of L4 micro kernel
    • 18.7 L4 Linux性能分析
  • Lec19 Virtual Machines (Robert)
    • 19.1 Why Virtual Machine?
    • 19.2 Trap-and-Emulate --- Trap
    • 19.3 Trap-and-Emulate --- Emulate
    • 19.4 Trap-and-Emulate --- Page Table
    • 19.5 Trap-and-Emulate --- Devices
    • 19.6 硬件对虚拟机的支持
    • 19.7 Dune: Safe User-level Access to Privileged CPU Features
  • Lec20 Kernels and HLL (Frans)
    • 20.1 C语言实现操作系统的优劣势
    • 20.2 高级编程语言实现操作系统的优劣势
    • 20.3 高级编程语言选择 --- Golang
    • 20.4 Biscuit
    • 20.5 Heap exhaustion
    • 20.6 Heap exhaustion solution
    • 20.7 Evaluation: HLL benefits
    • 20.8 Evaluation: HLL performance cost(1)
    • 20.9 Evaluation: HLL performance cost(2)
    • 20.10 Should one use HLL for a new kernel?
  • Lec21 Networking (Robert)
    • 21.1计算机网络概述
    • 21.2 二层网络 --- Ethernet
    • 21.3 二/三层地址转换 --- ARP
    • 21.4 三层网络 --- Internet
    • 21.5 四层网络 --- UDP
    • 21.6 网络协议栈(Network Stack)
    • 21.7 Ring Buffer
    • 21.8 Receive Livelock
    • 21.9 如何解决Livelock
  • Lec22 Meltdown (Robert)
    • 22.1 Meltdown发生的背景
    • 22.2 Speculative execution(1)
    • 22.3 Speculative execution(2)
    • 22.4 CPU caches
    • 22.5 Flush and Reload
    • 22.6 Meltdown Attack
    • 22.7 Meltdown Fix
  • Lec23 RCU (Robert)
    • 23.1 使用锁带来的问题
    • 23.2 读写锁 (Read-Write Lock)
    • 23.3 RCU实现(1) - 基本实现
    • 23.4 RCU实现(2) - Memory barrier
    • 23.5 RCU实现(3) - 读写规则
    • 23.6 RCU用例代码
    • 23.7 RCU总结
Powered by GitBook
On this page

Was this helpful?

  1. Lec19 Virtual Machines (Robert)

19.1 Why Virtual Machine?

PreviousLec19 Virtual Machines (Robert)Next19.2 Trap-and-Emulate --- Trap

Last updated 4 years ago

Was this helpful?

今天讨论的话题是虚拟机。今天的内容包含三个部分:

  • 第一个部分是Trap and Emulate,这部分会介绍如何在RISC-V或者QEMU上构建属于自己的Virtual Machine Monitor(注,有些场合也称为Hypervisor)。

  • 第二部分会描述最近在硬件上对于虚拟化的支持。

  • 最后是讨论一下今天的,它使用了第二部分中硬件上的支持。

首先什么是虚拟机?你可以认为这是对于计算机的一种模拟,这种模拟足够能运行一个操作系统。QEMU可以认为是虚拟机的一个例子(注,QEMU应该是属于VMM/Hypervisor)。

在架构的最底层,位于硬件之上存在一个Virtual Machine Monitor(VMM),它取代了标准的操作系统内核。VMM的工作是模拟多个计算机用来运行Guest操作系统。VMM往上一层,如果对比一个操作系统的架构应该是用户空间,但是现在是叫做Guest空间。所以在今天的架构图里面,上面是Guest空间,下面是Host空间(注,也就是上面运行Guest操作系统,下面运行VMM)。

在Guest空间,会有一个或者多个Guest操作系统内核,或许其中一个是Linux kernel。这里的Linux kernel会觉得自己就是个普通的内核,并在自己之上还运行一堆用户进程,例如VI,C Compiler。我们或许还有另一个Guest运行了Windows操作系统,同时也包含了Windows用户进程。所以,在Host空间运行的是VMM,在Guest空间运行的是普通的操作系统。除此之外,在Guest空间又可以分为Guest Supervisor Mode,也就是Guest操作系统内核运行的模式,和Guest User Mode。

VMM的主要目的是提供对计算机的模拟,这样你可以不做修改就启动普通的Linux,普通的Windows系统,并运行在虚拟机内,并且不用担心任何奇怪的事情发生。所以,VMM必须要能够完全按照实际硬件的行为来模拟Guest Supervisor Mode和Guest User Mode,尽管实际上不可能完全一样,我们之后会讨论VMM对于这两种模式的模拟。

那么人们为什么会想要使用虚拟机呢?实际中有很多原因使得人们会在一个计算机上运行多个相互独立的操作系统。在一个大公司里面,你需要大量的服务,例如DNS,Firewall等等,但是每个服务并没有使用太多的资源,所以单独为这些服务购买物理机器有点浪费,但是将这些低强度的服务以虚拟机的形式运行在一个物理机上可以节省时间和资金。

虚拟机在云计算中使用的也非常广泛。云厂商,例如AWS,不想直接出借物理服务器给用户,因为这很难管理。它们想向用户出借的是可以随意确定不同规格的服务器。或许有两个用户在一台物理服务器上,但是他们并没有太使用计算机,这样AWS可以继续向同一个物理服务器上加入第三或者第四个用户。这样可以不使用额外的资金而获得更高的收益。所以,虚拟机提供了额外的灵活性,这里借助的技术是:将操作系统内核从之前的内核空间上移至用户空间,并在操作系统内核之下增加新的一层(注,也就是虚拟机的内核是运行在宿主机的用户空间,虚拟机的内核通过新增加的一层VMM来对接底层硬件)以提供这里的灵活性。

还有一些其他的原因会使得人们使用虚拟机。第一个是开发内核,这就是为什么我们在课程中一直使用QEMU。能够在虚拟环境而不是一个真实的计算机运行XV6,使得这门课程对于你们和我们来说都要方便的多。同时对于调试也更容易,因为相比在物理计算机上运行XV6,在QEMU提供的虚拟机环境中运行可以更容易的提供gdb的访问权限。

最后一个人们使用虚拟机的原因是,通过新增的VMM提供的抽象可以实现更多的功能。例如,你可以为整个操作系统和其中的用户进程做一个快照,并在磁盘中保存下来。稍后再恢复快照,并将操作系统和其中的用户进程恢复成做快照时的状态。这可以增加运行的可靠性,或者用来调试,或者用来拷贝虚拟机的镜像并运行多次。除此之外,还可以将一个Guest操作系统迁移到另一个计算机上。如果你在一个物理计算机上运行了一个Guest操作系统,现在需要关闭并替换该物理计算机,你可以在不干扰虚拟机运行的前提下,将它迁移到另一个物理计算机,这样你就可以安全的关闭第一个物理计算机。

以上就是人们喜欢使用虚拟机的原因。虚拟机实际上应用的非常非常广泛,并且它也有着很长的历史。虚拟机最早出现在1960年代,经过了一段时间的开发才变得非常流行且易用。

对于这们课程来说,我们之所以要学习虚拟机是因为VMM提供了对于操作系统的一种不同视角。在操作系统的架构中,内核之上提供的封装单元(注,视频中说的是container,但是container还有容器的意思,所以这里说成是封装单元)是我们熟悉的进程,内核管理的是多个用户进程。而在VMM的架构中,VMM之上提供的封装单元是对计算机的模拟。VMM的架构使得我们可以从另一个角度重新审视我们讨论过的内容,例如内存分配,线程调度等等,这或许可以给我们一些新的思路并带回到传统的操作系统内核中。所以,在虚拟机场景下,大部分的开发设计研究工作,从传统的内核移到了VMM。某种程度上来说,传统操作系统内核的内容下移了一层到了VMM。

今天课程的第一部分我将会讨论如何实现我们自己的虚拟机。这里假设我们要模拟的是RISC-V,并运行针对RISC-V设计的操作系统,例如XV6。我们的目的是让运行在Guest中的代码完全不能区分自己是运行在一个虚拟机还是物理机中,因为我们希望能在虚拟机中运行任何操作系统,甚至是你没有听说过的操作系统,这意味着对于任何操作系统的行为包括使用硬件的方式,虚拟机都必须提供提供对于硬件的完全相同的模拟,这样任何在真实硬件上能工作的代码,也同样能在虚拟机中工作。

除了不希望Guest能够发现自己是否运行在虚拟机中,我们也不希望Guest可以从虚拟机中逃逸。很多时候人们使用虚拟机是因为它为不被信任的软件甚至对于不被信任的操作系统提供了严格的隔离。假设你是Amazon,并且你出售云服务,通常是你的客户提供了运行在虚拟机内的操作系统和应用程序,所以有可能你的客户运行的不是普通的Linux而是一个特殊的修改过的Linux,并且会试图突破虚拟机的限制来访问其他用户的虚拟机或者访问Amazon用来实现虚拟机隔离的VMM。所以Guest不能从虚拟机中逃逸还挺重要的。Guest可以通过VMM使用内存,但是不能使用不属于自己的内存。类似的,Guest也不应该在没有权限的时候访问存储设备或者网卡。所以这里我们会想要非常严格的隔离。虚拟机在很多方面比普通的Linux进程提供了更加严格的隔离。Linux进程经常可以相互交互,它们可以杀掉别的进程,它们可以读写相同的文件,或者通过pipe进行通信。但是在一个普通的虚拟机中,所有这些都不被允许。运行在同一个计算机上的不同虚拟机,彼此之间是通过VMM完全隔离的。所以出于安全性考虑人们喜欢使用虚拟机,这是一种可以运行未被信任软件的方式,同时又不用担心bug和恶意攻击。

前面已经指出了虚拟机的目标是提供一种对于物理服务器的完全准确的模拟。但是实际中出于性能的考虑,这个目标很难达到。你将会看到运行在Guest中的Linux与VMM之间会相互交互,所以实际中Linux可以发现自己是否运行在VMM之上。出于效率的考虑,在VMM允许的前提下,Linux某些时候知道自己正在与VMM交互,以获得对于设备的高速访问权限。但这是一种被仔细控制的例外,实现虚拟机的大致策略还是完全准确的模拟物理服务器。

论文