简介

课程网站:https://pdos.csail.mit.edu/6.828/2021/schedule.html

课程翻译:https://mit-public-courses-cn-translatio.gitbook.io/mit6-s081/

课程

Lecture1

Lecture3

隔离性(isolation)
不同应用程序进程之间应该相互独立。
假设不存在操作系统层,应用程序直接和硬件进行交互。会产生CPU调度问题(某个应用程序一直占用CPU,其他应用无法被调度)、内存安全问题(应用程序修改了其他应用程序的内存数据)

应用程序不能直接与CPU交互,只能与进程交互。操作系统内核会完成不同进程在CPU上的切换。所以,操作系统不是直接将CPU提供给应用程序,而是向应用程序提供“进程”,进程抽象了CPU,这样操作系统才能在多个应用程序之间复用一个或者多个CPU。

多个进程同一时间不可以使用同一个CPU核,一般都是分时复用。

fork抽象了CPUexec抽象了内存files抽象了磁盘。理解这些系统调用的抽象和隔离性。

防御性(Defensive)
需要考虑应用程序不能通过某些恶意手段使得操作系统崩溃或打破隔离,进而控制内核。由于内核拥有所有硬件资源,控制了内核就相当于可以做任何事情。

硬件和强隔离性
硬件对于强隔离的支持包括了:user/kernle mode虚拟内存
处理器有两种运行模式,分别是user modekernel mode。在不同运行模式下,其可运行的指令权限不同。(通过处理器上的一个bit标志位区分两种模式,并拒绝在当前模式下不该执行的指令)

普通权限指令(unprivileged instructions):如ADD、SUB、JRC等,允许所有应用程序执行。
特殊权限指令(privileged instructions):如设置page table、关闭时钟中断。是一些直接操纵硬件的指令和设置保护的指令。

用户态到内核态的切换是通过硬件中断、陷阱或异常机制实现的。

虚拟内存
每个进程都维护了自己独立的page table,将虚拟内存和物理内存进行映射,使得进程间的物理内存都不重合。保证了进程和进程间内存的隔离性。

User/Kernel mode切换
应用程序通过ECALL指令将程序的控制权交给内核。ECALL指令接收一个数字参数,代表想要调用的System Call。内核中的syscall会根据传入的参数去实际调用应用程序想调用的那个系统调用。

宏内核 vs 微内核
宏内核:整个操作系统代码都运行在kernel mode。大多数的Unix操作系统实现都运行在kernel mode。
优点:高集成性,可以提供很高的性能
缺点:内核复杂,容易引入BUG

微内核:在这种模式下,希望在kernel mode中运行尽可能少的代码。比如内核仅提供IPC,虚拟内存,page table的支持。像文件系统、虚拟内存等以用户应用程序运行在user mode。用户应用程序需要通过内核的IPC与这些文件系统、exec等进行调用。假设我们需要让Shell能与文件系统交互,比如Shell调用了exec,必须有种方式可以接入到文件系统中。通常来说,这里工作的方式是,Shell会通过内核中的IPC系统发送一条消息,内核会查看这条消息并发现这是给文件系统的消息,之后内核会把消息发送给文件系统。
优点:内核精简意味着更少的BUG和更高的安全性
缺点:性能低,需要多次用户空间-内核空间的跳转。以及无法共享缓存数据,如page cache。

Lecture4

虚拟内存

地址空间(Address Spaces)
某个应用程序所拥有的一段专属内存空间。

页表(Page Table)
页表是在硬件中通过处理器和内存管理单元(Memory Management Unit)实现。内存管理单元负责虚拟地址和物理地址的转换。也就是说CPU通过MMU和MEM交互。
每个进程有自己的地址关系映射表单,其地址保存在SATP寄存器上,当进程切换的时候内核会将SATP寄存器修改为对应进程的地址关系表单的地址。

地址转换表是以page为粒度的,一个page为4KB,需要12bit。
虚拟地址占39位。27位index,12位offset。
物理地址占64位,44位index,12位offset。

页表缓存