是否可以在不映射内核的情况下将进程映射到内存中?

Is it possible to map a process into memory without mapping the kernel?

OSDev wiki 说:

It is traditional and generally good to have your kernel mapped in every user process

为什么会这样?进程不能单独映射到内存吗?映射内核有什么好处,那不是浪费space吗?

此外,是否可以从用户 space 访问内核 space,我为什么要这样做?

It is traditional and generally good to have your kernel mapped in every user process

因此当您进行系统调用时,内核不必更改页面 tables 来访问它自己的内存。例如,始终映射所有物理内存使得 read 系统调用从页面缓存中的任何位置复制内容变得更便宜。

GDT 和 IDT 基地址是虚拟的 (lidt / lgdt) 所以中断处理需要至少包含 IDT 的页面及其指向的中断处理程序代码被映射 user-space 正在执行。

但是作为英特尔 CPUs 上 Meltdown 的缓解措施,其中 user-space speculative reads can bypass the user/supervisor page-table permission bit、Linux 实际上会取消映射内核的 大多数 ,而用户- space 执行。它需要保持 "trampoline" 映射,交换页面 tables 以在跳转到常规入口点之前重新映射内核,因此中断处理程序和系统调用可以工作。

is it possible to access the kernel space from the user space and why would I do that?

通常内核会禁用它。第 table 页条目有一个 user/supervisor bit which controls whether it can be used when not in kernel mode (i.e. ring 3, I think). The kernel can thus leave its memory mapped while still protecting it from read/write by user-space. (See also 。)

CPUs 具有支持此用例的性能特征:每个 PTE 中都有一个 "global" 位(如果设置)意味着 CPU 可以将其缓存在TLB 即使 CR3 发生变化(即跨上下文切换,当内核安装新页面 table 时)。内核为其包含在每个进程中的内核映射设置此项。

顺便说一句,这些内核映射可能只有一个 table 的物理副本,每个不同的用户树都有顶级页面映射级别 4 Table (PML4) -space 页 tables 简单地指向相同的内核 PDPTE 结构(most/all 其中实际上是 1GiB 大页面映射,而不是指向更高级别条目的指针)。请参阅上面链接的图表。


实际上内核允许用户space读取(和执行)的少量内存:内核将几个4k页面called the VDSO area映射到每个进程的地址 space(在虚拟内存的最顶部)。

对于一些简单但常见的系统调用,如 gettimeofday()getpid(),user-space 可以 call 在这些页面中运行(例如 运行 rdtsc 并通过内核导出的常量缩放结果)而不是使用 syscall 进入内核模式并在那里做同样的事情。这为现代 x86 CPU 上内核模式的往返节省了 50 到 100 个时钟周期,而且在分派到正确的系统调用之前不需要内核中的所有 save/restore 东西.


Is it possible to map a process into memory without mapping the kernel?

在 64 位内核上使用 32 位进程,整个 4GiB 虚拟地址 space 可供用户使用-space. (除了 3 个左右的 4k VDSO 页。)

否则(当user-space虚拟地址与kernel-space虚拟地址一样宽时)Linux将上半部分用于所有物理内存的内核映射(1G x86 上的大页面)。

i386 Linux 有一个配置选项来进行拆分 1:3,IIRC,进一步压缩内核,但允许更多的虚拟地址 space 用于 user-space 进程. IDK,如果这对于其他架构上的 32 位内核很常见,或者仅适用于 x86。

wouldn't that be a waste of space?

它占用了一些虚拟地址 space,但你应该拥有比物理内存更多的虚拟地址。如果不这样做,您将不得不付出更频繁地重新映射内存的速度成本。

这就是我们拥有 x86-64 的原因,所以虚拟地址 space 是 巨大的 。 48 位是 256 TiB,所以地址的一半是 128 TiB space。如果有必要/有用,未来的 CPUs 可以实现对更宽虚拟地址的硬件支持。 ()。也许这将成为一个更大的问题,非易失性 DIMM 提供比 DRAM 更高密度的内存映射存储,并且是大量使用这两种地址的原因 space.

如果在单个进程中需要超过 2GiB 的虚拟地址 space,请使用 64 位系统。 (或者,如果您需要不计其数的进程/线程,请至少使用 64 位内核。带有 PAE 运行 的 32 位内核有时会遇到内存分配问题。请参阅一些 https://serverfault.com/ 问题。)

有人 reposted on their blog some of Linus Torvalds' comments about PAE (Physical Address Extensions) 允许在仅 32 位的 x86 系统上拥有超过 4GB 的物理内存。简介:糟糕,即使有一个很好的内核端实现,它也肯定比 64 位内核慢。除了对英特尔工程师进行更有趣的侮辱之外,他们认为这是一个好主意并解决 32 位操作系统的问题。