Skip to content

现实世界

蹦床和陷阱帧可能看起来过于复杂。一个驱动力是 RISC-V 有意在强制陷阱时尽可能少地做事情,以允许非常快速的陷阱处理的可能性,这被证明是重要的。结果是,内核陷阱处理程序的前几条指令实际上必须在用户环境中执行:用户页表和用户寄存器内容。并且陷阱处理程序最初不知道诸如正在运行的进程的身份或内核页表的地址之类的有用事实。一个解决方案是可能的,因为 RISC-V 提供了受保护的地方,内核可以在进入用户空间之前隐藏信息:sscratch 寄存器和指向内核内存但受缺少 PTE_U 保护的用户页表条目。Xv6 的蹦床和陷阱帧利用了这些 RISC-V 功能。

如果内核内存被映射到每个进程的用户页表中(PTE_U 清除),则可以消除对特殊蹦床页的需求。这也将消除在从用户空间陷入内核时进行页表切换的需要。这反过来又允许内核中的系统调用实现利用当前进程的用户内存被映射的优势,从而允许内核代码直接解引用用户指针。许多操作系统已经使用这些思想来提高效率。Xv6 避免了它们,以减少由于无意中使用用户指针而导致内核中安全漏洞的机会,并减少为确保用户和内核虚拟地址不重叠所需的一些复杂性。

生产操作系统实现了写时复制 fork、惰性分配、按需分页、分页到磁盘、内存映射文件等。此外,生产操作系统会尝试在物理内存的所有区域中存储有用的东西,通常在进程不使用的内存中缓存文件内容。

生产操作系统还向应用程序提供系统调用来管理其地址空间,并通过 mmapmunmapsigaction 系统调用实现自己的页错误处理,以及提供将内存固定到 RAM 的调用(参见 mlock)和建议内核应用程序计划如何使用其内存的调用(参见 madvise)。