xv6book阅读 chapter2
一个操作系统至少应该满足三个需求:多路复用、隔离、交互。本章主要介绍如何组织操作系统来实现以上的三个需求,本文关注的是一种围绕单核进行设计的方法,这种设计是被许多uinx操作系统所使用的。Xv6运行在多核RISC-V微处理器上时,它的许多低级功能(例如,它的进程实现)是特定于RISC-V的,RISC-V是一个64位的处理器,而xv6是用“LP64”C语言编写的,这意味着C编程语言中的长(L)和指针(P)是64位,而int是32位,这里顺便复习一下指针的大小是和机器有关的,比如64位机器中指针大小就是8字节。xv6是为qemu的“-machine virt”选项模拟的支持硬件编写的。这包括RAM、包含引导代码的ROM、与用户键盘/屏幕的串行连接以及用于存储的磁盘,而qemu所模拟的环境是四个CPU内核的eixcv处理器。
1 抽象物理资源
为什么要有操作系统?操作系统可以做为一个系统调用的库,被所有运行在里面的程序所链接,而程序可以通过操作系统更好的使用硬件资源。通常进程总是会有bug并且不能很好的信任彼此,因此需要很好的隔离性。隔离性不仅仅指进程之间,还有进程与资源,进程与操作系统。
为了实现强隔离,禁止应用程序直接访问敏感的硬件资源,将资源抽象到服务中,是一种很好的方法。例如,Unix应用程序仅通过文件系统的open、read、write和close系统调用与存储交互,而不是直接读写磁盘,相当于把磁盘块抽象为文件。这样一来,操作系统才是真正的资源管理者,而不是用户。
2 用户模式、管理者模式以及系统调用
强隔离要求应用程序和操作系统之间有一个硬边界。如果应用程序出错,我们不希望操作系统失败,也不希望其他应用程序失败。操作系统应该能够清理失败的应用程序并继续运行其他应用程序。为了实现强隔离,操作系统必须安排应用程序不能修改(甚至读取)操作系统的数据结构和指令,并且应用程序的指令不能访问其他进程的内存。这里其实就开始引出为什么要有用户态和内核态了。
cpu为强隔离提供硬件支持。例如,RISC-V有三种CPU执行指令的模式:机器模式、管理者模式和用户模式。在机器模式下执行的指令具有完全权限;CPU以机器模式启动。机器模式主要用于配置计算机,Xv6在机器模式下执行几行代码,然后切换到管理者模式。还有一种方式就是通过页表来控制程序的访问范围。
在管理者模式下,CPU被允许执行特权指令:例如,启用和禁用中断,读取和写入保存页表地址的寄存器,等等。如果用户模式下的应用程序试图执行特权指令,则CPU不会执行该指令,而是切换到管理者模式,以便管理者模式代码可以终止应用程序,因为它做了一些不应该做的事情。应用程序只能执行用户模式指令(例如,添加数字等),被称为在用户空间中运行,而处于管理者模式的软件也可以执行特权指令,被称为在内核空间中运行。
上述三种模式是针对于CPU的,对于程序而言,它所执行的环境可以分为用户态和内核态,对应着CPU的用户模式和管理者模式(管理者模式其实就是内核模式,不过是不同处理器上的不同称为罢了)。一个想要调用内核函数的应用程序(例如,在xv6中读取系统调用)必须转换到内核态。CPU通常会提供一个特殊的指令,可以将CPU从用户模式切换到管理模式,并在内核指定的入口点进入内核(RISC-V为此目的提供了调用指令ecall)。
一旦CPU切换到管理者模式,内核就可以验证系统调用的参数(例如,检查传递给系统调用的地址是否属于应用程序内存的一部分),决定是否允许应用程序执行请求的操作(例如,检查是否允许应用程序写入指定的文件),然后拒绝它或执行它。重要的是,内核会控制过渡到管理器模式的入口点,否则恶意程序也可以随意进入内核态
3 内核架构
一个关键的设计问题是操作系统的哪个部分应该在管理者模式下运行。一种实现是整个操作系统驻留在内核中,因此所有系统调用的实现都以管理者模式运行。这种组织称为宏内核(a monolithic kernel)。
在这种组织中,整个操作系统以完全硬件特权运行。这种组织很方便,因为操作系统设计者不必决定操作系统的哪一部分不需要完全的硬件特权。此外,操作系统的不同部分更容易协作。例如,一个操作系统可能有一个缓冲缓存,它可以被文件系统和虚拟内存系统共享。
但宏内核的缺点就是操作系统中不同部分之间的接口设计很复杂,并且宏内核中产生的任何一个错误都是致命的,因为管理者模式中的错误通常都会导致cpu运行失败,这个时候必须重启才行。
为了减少在内核中出错的风险,操作系统设计者可以尽量减少在管理者模式下运行的操作系统代码的数量,并在用户模式下执行大部分操作系统。这种内核组织称为微内核。
在微内核中,文件系统可能作为用户级进程运行,作为进程运行的操作系统服务称为服务器。如果像shell这样的应用程序想要读取或写入文件,它会先向操作系统发送请求,操作系统转发消息给向文件服务器,返回的时候也是如此,总之无论是微内核还是宏内核,都是操作系统在管理着资源。
但无论是微内核还是宏内核,都是有很多相似的设计思想,比如它们都会有系统调用,处理中断、支持进程,支持锁,实现文件系统等。Xv6是作为一个宏内核实现的,因此,xv6内核接口对应于操作系统接口,内核实现完整的操作系统。
4 内核的文件组织
xv6内核源代码位于“kernel/”子目录下。源代码按照模块化的方式粗略划分为多个文件,如下图所示,模块间的接口定义在kernel/defs.h中
5 进程概述
进程是xv6内核中最小的隔离单位,内核用来实现进程的机制包括用户/主管模式标志、地址空间和线程的时间切片。Xv6使用页表(由硬件实现)为每个进程提供自己的地址空间。RISC-V页表转换(或“映射”)一个虚拟地址(RISC-V指令操作)到一个物理地址(CPU芯片发送到主存的地址)。
xv6为每个进程维护一个单独的页表,用于定义该进程的地址空间。地址空间包括从虚拟地址0开始的进程用户内存,如下图所示。首先是指令,然后是全局变量,然后是堆栈,最上面有两个特殊的区域trapframe和trampoline,这里对其分别解释一下:
1.trapframe:
trapframe
是一个数据结构,用于保存处理中断或异常时 CPU 寄存器的状态。它记录了中断或异常发生时,CPU 寄存器的值,以及一些其他与处理中断相关的信息。以便在中断服务例程(interrupt service routine,ISR)执行完毕后,能够正确地恢复进程的执行。- trapframe 中的信息可能包括程序计数器(PC)、堆栈指针(SP)、标志寄存器(FLAGS)、各种段寄存器等。
2.trampoline:
trampoline
是一段代码,通常是汇编代码,用于在用户态和内核态之间进行切换。当中断或异常发生时,CPU 需要从用户态切换到内核态,执行内核中对应的中断服务例程。trampoline 代码的作用是协助这个切换过程。- 在 xv6 中,trampoline 代码的一部分被放置在用户地址空间中,以便在用户程序发生中断时,能够正确地切换到内核态执行中断服务例程。
RSIC-V处理器上的指针是64位的,但在页表中查找虚拟地址的时候,硬件只使用低39位,因此进程空间的最大地址只能是2^38-1,对于最大地址空间的宏定义为MAXVA(kernel/riscv.h:363)
xv6内核为每个进程维护一个proc
结构体,用于保存进程的一些状态信息
(kernel/proc.h:86)。进程最重要的内核状态信息是他的页表、堆栈和运行状态。可以使用p->xxx来指代proc结构体的元素,如p->pagetable是指向进程页表的指针。
每个进程都有一个用于执行指令的上下文。这个上下文包括进程的寄存器状态、程序计数器(PC)以及其他与执行指令相关的信息。每个进程都在自己的地址空间中执行,有独立的寄存器状态和代码空间。而xv6book中所指的执行线程可以理解为上下文中可以执行指令的组成部分。每个进程有两个堆栈:用户堆栈和内核堆栈(p->kstack)。当进程执行用户指令时,只有它的用户堆栈在使用,而它的内核堆栈是空的。当进程进入内核时(对于系统调用或中断),内核代码在进程的内核堆栈上执行;当进程处于内核中时,它的用户堆栈仍然包含保存的数据,但是没有被积极使用。进程的线程在主动使用其用户堆栈和内核堆栈之间交替。内核堆栈是独立的(并且不受用户代码的影响),因此即使进程破坏了它的用户堆栈,内核也可以执行。
进程可以通过执行RISC-V调用指令来进行系统调用。该指令提高硬件特权级别,并将程序计数器更改为内核定义的入口点。入口点的代码切换到内核堆栈,并执行实现系统调用的内核指令。当系统调用完成时,内核切换回用户堆栈,并通过调用sret指令返回到用户空间,这降低了硬件特权级别,并在系统调用指令之后恢复执行用户指令。进程的执行线程可以在内核中“阻塞”以等待I/O,并在I/O完成后恢复到它离开的地方。
p->state
用于指示线程是在运行态、就绪态还是阻塞态,p->pagetable
指示进程的页表,当在用户空间中执行进程时,xv6的分页硬件会使用该页表。而一个进程的页表不仅用于映射虚拟地址到物理地址,同时也记录了分配给该进程存储内存的物理页面的地址。
总而言之,一个进程捆绑了两个设计思想:一个地址空间,给进程一个自己内存的错觉;一个执行线程,给进程一个自己CPU的错觉。在xv6中,一个进程由一个地址空间和一个线程组成。在实际操作系统中,一个进程可能有多个线程来利用多个cpu。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步