笔记06 - x86 v6 book | Chapter 1 Operating system organization

Operating system organization

操作系统组织

os requiement: 实现一个操作系统必须完成三个要求,multiplexing、isolation和interaction,即多路复用、隔离和交互。
isolation: 如果一个进程因为出现bug而失败,不应该影响那些没有依赖于该进程的其他进程。由于操作系统必须保证进程间的交互,因此完全隔离的难度大。

Abstracting physical resources

对物理资源进行抽象

why have an os at all?: 原本可以将系统调用实现为库,并使应用程序链接该库来访问物理资源。这样的话,每个应用程序甚至可以拥有自己的库,应用程序可以直接与硬件资源进行交互,并通过最好的方法来使用这些资源(如实现高性能和可预测的性能)。这种方案的缺点是应用可以自由使用库,也可以不使用库。如果它们不使用操作系统的库,操作系统将无法强制实施分时共享。为了实现分时,需要依赖应用程序本身正确的行为(比如按时放弃处理器),这种合作性的分时共享方案在所有应用程序都信任彼此的情况下可能是可行的,一旦应用程序相互不信任,将不提供strong isolation。
how to achieve strong isolation?: 不允许应用程序直接访问硬件资源,而是将资源抽象为services。比如,应用程序与文件系统的交互仅通过open/read/write/close的系统调用,这为应用程序提供了方便的路径名,也允许操作系统管理硬盘。比如,应用程序通过fork系统调用来执行进程,当切换不同进程的时候由操作系统替代应用程序来保存和恢复寄存器,应用程序不需要知道进程切换,进一步地,这允许OS强行切换使用处理器的应用程序。比如,应用程序通过exec来创建进程的内存映像,而不是直接与物理内存进行交互,这允许OS能决定将进程的内存位置,内存缺页时可以移动内容,并提供文件系统来存储映像。
how to support controled interaction between applications: unix的应用程序只能使用文件描述符,而不能自行编写一些共享约定(如保留一块内存)。文件描述符抽象了所有共享细节,隐藏了应用程序与终端、文件系统或管道交互的细节,并允许OS控制交互过程。

User mode, kernel mode, and system calls

why need kernel mode and user mode?: 应用程序和OS之间需要严格界限来为使用系统调用的软件和实现系统调用的软件提供强隔离。这种强隔离意味着应用程序不能改写由OS维护的数据结构,不能改写OS指令。处理器在内核模式和用户模式下执行指令,在内核模式下,处理器可以执行特权指令。如果在用户模式下的应用程序尝试执行特权指令,处理器将不会执行该指令,而是切换到内核模式,这样软件就可以在出现非法行为时清理该应用程序。应用程序在用户空间执行user-mode instructions,在内核空间执行kernel-mode instructions的软件被称为内核。如果用户模式下的应用程序需要读写硬盘,它必须过渡到内核去执行IO指令。处理器提供了特殊指令将处理器从用户模式切换到内核模式,并在内核指定的入口点进入内核。在切换到内核模式时由内核设置入口点是非常重要的,如果是由应用程序设定,则恶意应用程序能够在进入内核时跳过验证参数。

Kernel organization

what part of the OS should run in kernel mode: 所有内核接口都是系统调用接口,因此 fork, exec, open, close, read, write等都是内核调用,意味着OS的完整实现都是在内核模式下执行,这种内核组织称为monolithic kernel,即单内核。
monolithic kernel and microkernel: 在单内核方式下整个OS在full hardware privilege下运行,OS设计者不需要决定哪部分OS不需要运行在full hardware privilege下,OS不同部分也能更容易地协作。单内核方式的缺点是OS不同部分的接口经常很复杂,开发者容易出现错误。为了降低这个风险,OS设计者可以最小化运行在内核模式下的代码,将不需要执行特权指令的部分作为用户级应用程序,这种组织称为microkernel。作为普通用户程序运行的服务通常被称为server,比如,文件系统以用户级应用程序执行。为了允许应用程序和file server的交互,内核提供了一个最小机制从一个用户模式的应用程序发送消息到另一个应用程序。

Process overview

process: xv6实现隔离的单元是process。进程抽象阻止一个进程破坏或监视另一个进程的内存、CPU、文件描述符等,阻止进程破坏内核本身。内核使用的进程实现机制包括user/kernel mode标识、地址空间、线程的time slicing。一个进程是一个抽象,提供给程序这样的错觉:程序拥有自己抽象机器、内存系统和CPU。xv6使用页表(由硬件实现)为每一个进程提供地址空间,维护一个单独的页表用以定义每个进程的地址空间。

process’s address space: 每个进程的地址空间会映射到内核指令、数据,以及用户程序的内存。当一个进程调用系统调用,系统调用将在映射到该进程地址空间的内核上执行。这样的设计使得内核的系统调用代码可以直接访问用户内存。

thread: 每个进程都有一个执行线程来执行进程指令。为了透明地在不同进程间进行切换,内核中止当前正在运行的线程并恢复另一个进程的线程。大部分的线程状态(局部变量、函数调用返回地址)存储在线程的stacks中。每个线程都有两种stacks,user stack和kernel stack。当进程执行用户指令时,只有用户堆栈被使用,其内核栈是空的。当进程进入内核时,内核代码在进程的内核栈上执行。当一个进程进入内核模式,其用户栈仍然保存数据,但不被使用。进程的执行线程在用户栈和内核栈之间进行交替使用。内核栈是分开的并被用户代码保护,即使进程破坏了它的用户栈,内核也可以执行。当一个进程调用系统调用,处理器切换到内核堆栈,提高硬件特权级别,并开始执行内核指令以实现系统调用。当系统调用完成时,内核返回用户空间,硬件降低其特权级别,交换回用户堆栈,恢复执行系统调用指令之后的用户指令。

Layout of a virtual address space

显示 Gitment 评论