Xv6 操作系统

2025 年 4 月 29 日 | 阅读 23 分钟

引言

操作系统 (OS) 是现代计算的核心,负责管理硬件资源、运行应用程序并为用户提供基本服务。对于任何想要在该领域取得进展,甚至追求通常被称为“计算机科学”的工作的人来说,例如系统编程和安全等,以及处理硬件,理解操作系统是一个基本概念。

然而,信息丰富且功能齐全的“优点”可能会使像 LinuxWindows 这样的现代操作系统对任何用户来说都变得复杂。欢迎来到 xv6 - 一款 类 Unix 操作系统,它消除了所有非必要的干扰,同时仍然是一个完全可用的操作系统。xv6 由麻省理工学院 (MIT) 的学生创建,用于教授操作系统和 CX,它是 Unix Version 6 (v6) 的一个版本,Unix 操作系统开发于 20 世纪 70 年代。

什么是 Xv6?

最小的类 Unix 操作系统,实际上用于教育目的以及操作系统专业学生的研究。该操作系统课程由麻省理工学院 (MIT) 的教授开发,用于“操作系统工程”,本网站的目的是通过一个最初由 MIT 学生于 2003 年作为其 OS 项目一部分创建的“干净、可读”版本的 Unix 来解释操作系统的基本思想和原理;此版本基于 Unix Version 6 (v6),这是 Unix 的早期版本之一。当然,Unix v6 本身作为操作系统是 OS 历史上的一大步,但 xv6 代表了对 Unix v6 的类似重新实现和升级,主要目标是作为教育工具,使用 C 语言和一个简单的 硬件 抽象层。

xv6 被许多学院和大学广泛使用,这可能归因于它是一个简单的操作系统。与 Linux 等现代操作系统包含数千万条命令不同,xv6 仅包含约 9000 条 C 命令和一些汇编指令。由于其紧凑性,整个系统都可以被阅读、理解甚至修改,特别是对于希望获得系统实践经验的学生和好奇的开发人员来说,这是大型系统无法提供的。

为什么选择 Xv6?

从基本知识开始学习操作系统可能非常令人生畏。现代配置已发展到包含多个层次的层次结构,以解决多种硬件类型、支持多个用户以及解决网络和安全等高级功能。这种情况虽然有利于在现实世界中进一步发展 OS 问题,但不可避免地会削弱 OS 设计的基本概念。因此,对于学习者来说,xv6 是解决这种复杂性的方法。

名为 xv6 的课程缺少许多复杂性和层次,这些复杂性和层次是你在 OS 中可能发现自己团团转的东西。Xv6 倾向于简化,使得学生更容易理解 OS 如何处理进程、内存和文件系统,同时让学生接触并发、系统调用、中断以及 OS 中的许多其他概念。正如预期的那样,xv6 是一个功能齐全的操作系统,支持基本的类 Unix 进程管理、文件系统和一个简单的 shell。这使其成为一个完美的教学辅助工具,因为它附带了完整的解释,同时又易于应用。

Xv6 中的 Unix 传承

为了更好地了解 xv6,本文将首先介绍 Unix v6 是什么以及 xv6 是如何从中诞生的。Unix v6 于 1975 年发布,它是现代操作系统之所以成为今天的样子的重要原因。这些是分层文件系统和用户模式进程以及系统调用,程序能够通过这些调用向内核请求服务。

Unix v6 一直以其简洁优雅而闻名,xv6 也不例外。它重新实现了 Unix v6 的进程、内存、文件系统和 I/O,但以一种对当今学习者来说更熟悉的方式。此外,该作品在 XV6 中进行了一些小的增强,以适应现代技术和程序员的习惯。例如,Unix v6 主要用汇编语言实现,这与 XV6 主要用 C 语言实现的方式截然不同;这种实现方式不仅使当今的学习者更容易,而且还为移植到当今大多数硬件平台提供了机会。

Xv6 架构概述

xv6 操作系统的设计使得能够连贯简洁地了解构成任何类 Unix 系统基础的知识。xv6 以教学为目的,提供了一个可理解的结构,包含了操作系统必不可少的组件,包括进程、内存和文件系统。

1. 内核结构

xv6 的核心是内核,一个在监管模式下运行的大型单程序,负责系统的大部分设备功能。而在微内核架构中,不同的服务位于不同的进程中,在 xv6 中,它们完全在内核空间实现。与当今的系统相比,这种架构的模块化程度稍低,安全性也低得多,但其优点是更容易在操作层面进行理解和管理。

内核负责:

  • 进程管理:管理进程的创建、执行、调度和终止。
  • 内存管理:了解内存分配给进程的过程以及虚拟内存管理。
  • 文件系统:文件管理、目录管理和 inode 管理。
  • 进程间通信 (IPC)实现进程间的多种通信方式。
  • 设备驱动程序:管理磁盘、键盘和控制台等硬件设备。

这些功能中的每一个都可以用少量易读的代码来实现,并且它们都紧密地集成在内核中;也就是说,学生可以很好地了解操作系统如何从系统的角度工作。

2. 进程和进程管理

线程是 xv6 中最小的可执行实体,OS 提供了一个简单而高效的线程管理模型。与 Unix 类似,xv6 使用进程来表示正在运行的程序并封装其状态,包括:

  • 进程 ID (PID):每个活动的唯一标识号。
  • 程序计数器 (PC):在程序控制中要执行的下一条指令的级别地址,程序或进程可以直接在此处执行。
  • 寄存器状态:为上下文切换存储的 CPU 寄存器的值。
  • 页表:解释虚拟内存如何对应于该进程的物理内存。

xv6 支持用于进程创建或执行的系统调用;fork():克隆父进程 P,创建子进程,而 exec():用要执行的程序替换当前进程映像。当进程完成时,它可以调用 exit(),OS 负责清理资源。

3. 进程调度

循环调度是 CPU 调度算法中最简单的之一,并在 xv6 中实现。任务按圆形系统组织,每个进程都有一个预定的执行时间间隔。如果一个进程在其时间片内未完成,它将被中断,并且下一个进程获得 CPU 时间片。

尽管简单,但调度程序用于解释简单的调度功能,例如上下文切换,其中保存进程的状态,并检索另一个进程的状态以允许共享 CPU。这种同步协作式并发对于 xv6 这样的小型系统来说相当不错,因为节俭比效率更重要。

4. 内存管理

在 xv6 中,一些内存管理概念比当今操作系统模型更基础,但它们足以说明虚拟内存和分页等关键思想。每个进程都有另一个虚拟地址空间,地址空间通过页表转换为物理地址。

  • 页表:xv6 中的虚拟地址空间是一个两级页表,因此我们必须在虚拟和物理寻址之间进行转换。这种结构是通过利用 x86 处理器的一些硬件特性来实现的。
  • 物理内存分配:xv6 使用空闲列表分配器,这是一个由所有空闲内存页组成的列表,这些页以连续列表的形式连接。当进程需要内存时,分配器将页面分配给该进程。当内存被释放时,它会返回到空闲列表。

5. 文件系统

与教学文本类似,xv6 也有一个文件系统,这是了解类 Unix 系统数据管理的另一个重要功能。xv6 中实现的文件系统是一个简单的基于 inode 的文件系统,这是 Unix 系统的特征。文件的数据存储在称为 inode 的节点中,这些节点包含文件相关的信息,例如其大小、权限和在磁盘上的位置。

  • 目录和文件:在 xv6 中,目录被归类为唯一的文件,包含文件名和 inode 号之间的关联。这导致创建了一个分层文件系统,其中目录可以包含另一个目录或文件。
  • 文件操作系统调用:xv6 提供基本的文件系统操作,包括 open()、read()、write() 和 close()。这些系统调用允许进程以有序的方式使用文件,并将它们与读写磁盘数据的细节隔离开来。

6. 进程间通信 (IPC)

在 xv6 中,两个进程之间的通信可以通过系统调用完成,例如 pipe()。管道允许数据以单向方式从一个进程传递到另一个进程。在更高级的系统中,IPC 可以通过消息传递、共享内存或信号量来实现,但为了简单演示进程如何通信和协调其任务,xv6 使用管道。

7. 中断处理和设备驱动程序

xv6 调度由中断创建的对象,用于异步事件,如 I/O 操作。当发生中断时,例如键盘按键或磁盘读取过程,CPU 会暂停当前进程并将控制权转移到操作系统内核的一部分的中断处理程序;xv6 包含两个非常简单的 I/O 设备驱动程序,用于磁盘和控制台,以说明 OS 如何与硬件通信。

  • 中断处理:与定时器滴答或硬件 I/O 等事件同时发生的中断服务例程 (ISR) 是让进程即时接口事件的机制。

xv6 中的进程是什么?

同样,在 xv6 中,进程只是指一个正在运行的程序。每个进程都有自己的

  • 代码(文本):中央处理单元处理的程序。
  • 数据:程序的变量和内存位置。
  • 堆栈:用于存放函数调用、局部变量以及数据执行的环境。
  • 寄存器:文件状态信息、程序计数器(PC)的当前值、堆栈指针(SP)的当前值以及通用寄存器的当前值。
    进程结构中还有很多信息,称为进程控制块 (PCB) 或 xv6 中的 proc。这个结构保存了每个进程的关键信息
  • 进程 ID (PID):它是系统中区分每个进程的特殊编号。
  • 状态:上次更新时间以及进程的当前状态——可以是运行、睡眠、等待或僵尸。
  • 程序计数器:下一条要获取或执行的指令的逻辑或程序地址,取决于当前的计算机模式。
  • 寄存器: CPU 寄存器的非活动存储值是进程不活动期间上下文切换的结果。
  • 内存分配:关于进程地址空间与应用程序地址空间之间关系的信息,其中应用程序地址空间将包含进程的代码、数据和堆栈。
  • 文件描述符:指向进程使用的打开文件的文件编号。

Xv6 中的进程创建

在 xv6 中,进程创建通过 fork() 系统调用完成,该调用类似于 Unix 的 fork() 调用。在 fork() 中,新进程的创建涉及复制当前进程。新进程称为子进程,它被映射到父进程的精确副本,连同其点和内存空间。

  • Copy-on-fork:xv6 拥有父进程内存映像的精确副本。因此,子进程拥有其唯一的地址空间。但是,这类系统与其他更高级的系统(如 Linux)不同,Linux 采用写时复制来隔离内存使用。
  • 父子关系:在 fork 之后,父进程和子进程都将同时运行,这使得程序很有趣。子进程将拥有与父进程相同的代码、数据和文件描述符,但进程 ID 号不同。

进程执行:exec()

虽然 fork() 创建一个克隆父进程的新进程,但 exec() 系统调用允许进程用另一个程序的内存空间替换其自身的内存空间。这对于处理新工作负载或应用程序至关重要,因为它们需要提供卓越的应用程序性能。

  • exec() 的工作原理:如果一个进程尝试对其调用 exec(),那么进程的旧内存内容(代码、数据和堆栈)将被清除,新程序将被加载到内存中。新程序从其第一条语句开始执行,直到程序的最后一条语句完成。
  • 进程 ID:执行 exec() 调用的进程保留其进程 ID,但其上下文将完全修改以对应新程序的上下文。

此系统调用展示了操作系统如何管理多个程序:应用程序可以从另一个程序的副本开始,但然后在其地址空间中下载另一个程序。这实际上很常见,例如,shell:shell 会 fork 一个新进程,然后使用 exec() 执行用户命令。

xv6 中的进程状态

xv6 中的每个进程可以处于几种状态之一,这些状态描述了进程在任何给定时间正在做什么

  • 未使用:进程槽是空的。
  • 胚胎:进程正在创建中。
  • 睡眠:一项活动正在等待事件或资源,例如等待输入。
  • 可运行:进程已准备好进入下一阶段,我们只等待 CPU 时间片。
  • 运行:进程当前由中央处理单元执行。
  • 僵尸:这意味着进程已完成运行,但其父进程尚未获取退出值。

在它们的生命周期中,它们会根据诸如资源分配和 CPU 调度程序等因素在这些模式之间转换。例如,一个进程可能会从睡眠状态唤醒到可运行状态,因为它收到了一些输入,然后由于调度程序选择了它而进入运行状态。

进程调度

在 xv6 中,多个进程的调度通过循环调度技术有效地完成,该技术基本但高效。在循环调度中

每个进程都被预先测量了允许执行的固定时间量。

即使进程在其时间片内未完成,它也会被中断,并且下一个进程有机会运行。

在所有进程完成此轮之后,调度程序会返回到列表中的初始进程。

这种抢占式多任务处理有助于确保进程永远不会占用 CPU,从而使 xv6 成为一个多任务系统。上下文切换发生在进程时间量结束时,此时 OS 将保存当前进程的状态(寄存器、程序计数器等)并调出下一个进程的状态。

进程终止

xv6 中的特定进程使用系统退出调用或 exit 系统调用退出,该调用会退出进程并释放它使用的内存以及任何打开的 FD。但是,这个过程并非一气呵成。它进入僵尸状态,在那里它一直停留,直到其父进程通过 wait() 系统调用收集僵尸进程的终止状态。

exit() 和 wait() 系统调用是进程管理中的基本父级调用,用于同步父子进程。父进程可以查找子进程的状态并清理任何剩余资源,这对于维护系统完整性并确保没有资源泄漏很重要。

xv6 中的内存管理

1. xv6 中的虚拟内存

xv6 的核心原则之一是虚拟内存。进程不是直接指向物理内存,而是各自在其自己的虚拟地址空间中工作。这种抽象提供了几个好处

  • 进程隔离:每个进程都有自己的虚拟地址空间,因此一个进程不能读取或写入另一个进程的空间,这也提高了安全性和可靠性。
  • 简化的编程模型:每个进程都可以自由地假设它处理一个连续的内存空间区域,而物理内存可能分散。
  • 内存保护:操作系统可以在应用程序内指定权限,使得某些区域只能读写,而某些区域只能执行。

与大多数现代操作系统一样,xv6 中的虚拟内存通过分页映射到物理内存。进程的系统地址空间被划分为页面——固定大小的块,其中每个虚拟页面都映射到物理内存中的物理帧。从虚拟地址到物理地址的转换是通过页表完成的。

2. 页表和地址转换

页表对于 xv6 内存管理至关重要。它们是 OS 用于将应用程序的虚拟地址复制到物理地址的数据结构。每当进程发出内存指令时,它都必须将其转换为物理地址。这分两步完成

使用最高有效位(称为页号)来索引页表,从而转换虚拟地址。

PTW 中实际包含的信息是物理页号以及该页的权限位(可读或可写)。

xv6 的架构基于 x86 处理器,使用两级页表

第一级是页目录,包含页表的地址。

第二级是页表本身,它保存物理地址或物理标识符的位置。

此外,它建立了两个层次结构,有助于最小化大型系统和虚拟地址空间的页表管理内存开销。它还负责请求内存管理,并允许系统确定当前哪个页面在内存中。

3. 物理内存分配

尽管虚拟内存有助于组织进程,但实际数据必须存储在物理内存中,在这方面,xv6 提供了一种最简单但有效的方法。

xv6 使用空闲列表进行物理内存管理,通过它可以获取或释放可用的物理内存。空闲列表本质上是一个包含要分配的空闲内存页或帧的开放列表。如果进程需要从操作系统的空闲内存中为自己请求更多内存,则 OS 将从此空闲列表中选择一个页面。一方面,如果进程不需要内存,例如进程结束时,其页面会返回到空闲列表。

kalloc() 从空闲列表中提取页面,而 kfree() 在不再需要时用于将页面放回。这些函数在整个 OS 中用于根据需要控制内存空间的需求。

4. 内存管理系统调用

xv6 提供多个系统调用,允许进程管理其内存

  • sbrk():此系统调用可用于增加或减少进程的地址空间。Sysallocates 根据提供的字节数增长进程的数据段(堆)。为了满足更多内存的请求,sbrk() 使用 allocuvm() 函数,该函数为进程地址空间分配新页面。
  • allocuvm() 和 deallocuvm():这些内部函数用于分配和释放进程的虚拟内存空间。allocuvm() 向进程地址空间添加新页面,并将更多虚拟可寻址空间映射到实际物理帧。另一方面,deallocuvm() 函数从进程的地址空间中移除页面,从而减小进程的大小。

总而言之,这些函数允许动态堆根据进程的执行进行更改,在需要时进行增长和收缩。

5. 内核内存管理

除了组织用户进程的内存之外,xv6 还必须组织内核自己的内存空间。操作系统内核在与用于其任务(即进程)的内存不同的特殊内存区域中运行,并且该内存映射到单独的页表。

内核内存的分配方式与用户内存类似,都使用空闲列表。然而,内核内存是长期的,并且以不同的方式管理,以确保内核保持出色的响应能力。例如,某些内存区域(内存映射 I/O 区域)是永久分配的,不能被交换或释放。

6. xv6 内存管理限制

  • 无交换:此外,与许多其他操作系统不同,xV6 不使用交换——所有活动内存都必须容纳在物理 RAM 中。在真正的现代系统中,它们使用内存交换,当 RAM 已满时,内核会将物理 RAM 中的内容移到磁盘,但在 xv6 中,它缺少此功能以减轻复杂性。
  • 无高级内存优化:其他选项,如写时复制、内存重复数据删除或透明大页,也缺失。这些功能在当前操作系统中很常见,用于节省内存。

xv6 中的中断和系统调用

1. xv6 中的中断

中断是由外围设备或其他程序发出的一种电信号或机械信号,请求关注。xv6 中的中断由计时器、磁盘、键盘等设备产生,必须由操作系统有效处理。

2. 中断类型

  • 硬件中断:由外部世界(例如,按键或计时器滴答)的事件触发。为了吸引 CPU 的注意力到某个特定的硬件设备,该设备会发送一个中断信号。
  • 软件中断:也称为陷阱,它们由软件程序中特殊指令的执行产生,包括零除法或系统调用请求。

3. 中断处理过程

发生中断时,CPU 会暂停当前任务,并保存所有寄存器的状态,这称为上下文切换,然后转到内核的另一部分,即中断处理程序/中断服务例程。在 xv6 中,内核按以下步骤处理中断

  • 保存上下文:CPU 冻结其当前工作,将当前进程置于暂停所有寄存器、程序计数器等的状态。
  • 切换到内核模式:CPU 从用户模式(在 C 结构中通常称为 ring 3)切换到内核模式,该模式允许内核访问特权指令和其他内存区域。
  • 中断向量:xv6 采用中断向量表来启用相关数字和中断处理程序的映射。CPU 使用该表确定必须执行哪个特定的 ISR。
  • 执行 ISR:硬件禁用标志在特定于中断类型的中断处理程序通过传输或退休执行转换措施之前一直设置。例如,键盘中断处理程序扫描键盘,而计时器中断处理程序则提供新时间或实现进程调度。

4. xv6 中的系统调用

系统调用是用户程序向操作系统请求服务的途径。由于用户模式下的进程可能会出于安全性和可靠性考虑而干扰内核,因此内核通过系统调用选择性地公开硬件设施和其他内核支持的操作。

5. 系统调用机制

  • 陷阱指令:为了使用系统调用,用户进程执行陷阱指令,这会导致软件中断。在 x86 架构中,这是 int 指令(例如,Linux 中的 int 0x80)。
  • 切换到内核模式:与中断一样,CPU 会进入内核模式,允许进程访问受保护的内核数据。
  • 系统调用号:陷阱指令还提供一个系统调用号,告诉操作系统进程想要做什么系统调用。此编号写入特定寄存器(例如,x86 架构的 eax);其他寄存器包含系统调用的参数。
  • 系统调用处理程序:内核中的系统调用处理程序会调用系统调用号,从系统调用表中获取相应的系统调用函数。它通过执行针对特定请求的正确函数来执行此操作。
  • 返回用户模式:一旦用户进行了系统调用,内核将处理该请求,然后将控制权通过寄存器中的返回值传递回用户进程。

6. xv6 中的常用系统调用

  • Fork ():从调用进程分叉一个子进程,同时建立一个新进程。子进程从父进程内存创建其内存,并从同一起点开始。
  • Exec ():断开调用进程的内存并加载另一个程序。此系统调用用于创建新进程……
  • exit():导致调用进程退出;放弃其系统资源。
  • Wait ():因此,它导致父进程等待直到子进程完成终止。
  • Read ():进程从文件或设备中提取信息并将其存储在进程空间中。
  • Write ():将进程内存中的信息记录到文件或设备中。
  • sbrk():通过为进程提供更多使用空间或释放进程先前使用的空间来增加或缩小进程的堆。

xv6 的并发与同步

1. xv6 中的并发

并发是指一个或多个进程或线程同时处于活动状态,或者一个进程正在运行一部分,而另一个进程正在执行另一部分。在 xv6 中,这是通过多进程和多线程来实现的,如下所述。并发意味着可以同时进行多个操作,从而提高了 CPU 利用率和系统性能。

2. 通过进程实现并发

在 xv6 中,每个进程都在自己的空间中执行,该空间具有特定的内存和特定的 CPU 状态。所有进程都可以自由交互,但可以同时进行,因为 xv6 使用抢占式多任务处理,其中操作系统在特定间隔(通过定时器中断)检查进程,然后允许它在进程之间切换。

3. 通过中断实现并发

因此,中断除了我们在进程级别看到的之外,还提供了另一层并发。中断可能来自计时器或 I/O 设备,并且可能会随机发生,从而激活内核中的中断处理程序。这些处理程序与其他的内核和用户进程并行处理,因此,数据需要非常敏感地管理。

4. 内核中的并发

内核本身也应该是并发的,因为并发系统调用、中断和进程可能出现在内核区域。如果不加以控制,同时访问某些共享内核结构,如进程表、内存分配器等,可能会导致数据处理不当,甚至系统挂起。

5. xv6 中的锁

锁是 xv6 中实现的主要同步形式。锁是一种同步原语,其标准是每次只允许一个线程或进程访问共享数据。基本机制是,当进程或线程获得锁时,其他正在寻求锁的进程或线程必须等待直到锁被释放。

6. xv6 中的锁类型

  • 自旋锁:自旋锁是一种锁定机制,它使进程或线程不断检查锁何时可用。自旋锁在 xv6 中用于代码中预期锁被短暂持有的区域。
    进程通过以某种方式标记锁结构来尝试获取锁。如果另一个进程已经持有锁,则其标志被设置,并且我们的进程进入永久循环旋转,等待释放标志。
    当锁被持有的时间很短时,自旋锁效果很好,而当锁被持有的时间很长时,它们可能会浪费 CPU 周期。
  • 睡眠锁:xv6 也有睡眠锁形式,如果进程没有获得锁,它就会睡眠(或被阻塞)。该进程会进入睡眠状态,直到锁被释放。然后,它会被唤醒并允许运行。如果预计锁被持有时间较长,则使用睡眠锁,因为旋转只会消耗 CPU 时间。

7. 锁实现

xv6 中自旋锁的结构通常包括

  • 一个特殊标志,指示锁是否被持有。
  • 持有该锁的进程的标识,以便可以有效地进行调试。
  • 一个睡眠锁数组,包含以下信息:等待锁的所有进程的列表。

8. 睡眠与唤醒机制

xv6 对进程同步、睡眠和唤醒都有基本支持。进程可以调用 sleep() 来暂停自身,直到特定事件发生。当另一个进程或中断处理程序更改条件时,它会使用 wakeup 来唤醒睡眠进程。

  • sleep (chan, lock):进程调用 sleep() 来阻塞给定的通道 chan。在睡眠之前,进程会释放它所持有的锁,以避免陷入死锁。在睡眠期间,进程会从运行队列中移除;此外,直到它醒来才会安排运行。
  • wakeup (chan):另一个进程或中断处理程序调用 wakeup() 函数,该函数会唤醒在该通道上运行的所有进程。这意味着一旦进程被唤醒,它们就会被放回运行队列,并可以被允许运行。

xv6 与现代操作系统的比较

xv6 作为学习平台创建,其进程管理系统比当今的操作系统简单得多。xv6 中的进程以相对简单的方式进行调度,采用最简单的循环调度系统,未实现多线程和优先级。如今的操作系统,例如 Linux、Windows 和 Mac OS,拥有高度增强的调度程序;例如,Linux 中的 CFS 处理许多具有不同优先级的进程,并以最佳方式分配 CPU 时间。此外,当代系统旨在支持并与多线程应用程序、内核级别和用户级别进程隔离的实时任务配合使用。

Xv6 实现简单的分页,不使用交换或多层虚拟内存等复杂技术。它通过将物理内存与进程的虚拟地址空间关联来处理物理内存,而没有当今一些高级选项,如分页内存(当需要时才将一部分内存加载到物理内存)、共享内存或过于复杂的内存保护方案。然而,大多数当前操作系统都使用复杂的虚拟内存系统,包括内存映射文件、共享内存以及诸如写时复制 (COW) 和交换等虚拟内存方法来处理复杂的这些工作负载。

如今,与 xv6 类似,它缺乏可靠的文件系统权限、设备驱动程序和网络功能,但在安全性、设备控制和接口方面优于 xv6。另一方面,现代 OS 具有高度发达的硬件抽象,支持多种类型的外围设备,复杂的用户身份验证和多用户环境,以及强大的网络堆栈。此外,当前 OS 拥有复杂的图形用户界面 (CUIs),而 xv6 只有一个终端界面。

结论

源自 Unix Version 6,它消除了 OS 中大部分的现代复杂性,以便学生能够开发 Boston,并且设计简单,可以让你专注于进程、内存、系统调用和同步的基本原理。通过 xv6,学习者可以实际了解操作系统是如何构建的,以及它如何与硬件通信或管理其他重要资源。使用 xv6 的关键收获包括

  • 理解进程管理基础知识:从使用 fork() 系统调用创建新进程,到使用 exec() 替换内存映像,xv6 在其进程方法方面具有教育意义。
  • 内存管理:xv6 是一个有用的工具,可以展示内存分配以及分页和虚拟内存的过程。
  • 中断处理和系统调用:如果学习者查看 xv6 中的中断和系统调用,他们将能够理解硬件如何与软件接口的底层方式。
  • 并发和同步: xv6 实现了一些基本的锁定原语,这对于理解真实操作系统如何处理并发非常重要。
  • 调试和修改: 因此,每个人都可以基于 xv6 进行学习和实现各种修改,这在某种程度上是件好事,因为每个人都可以有一个自由的试验场来实现新的系统调用,甚至可以在现有内核上添加新的内核。