Linux上的高内存和低内存是什么?


92

我对Highmem和Lowmem之间的区别感兴趣:

  1. 为什么会有这种差异?
  2. 这样做有什么好处?
  3. 每个都有什么功能?

@hiro,您的意思是“ HIGHMEM”是ldd3所描述的“内核虚拟地址”。我同意你的看法。令人困惑的是,ldd3定义了“ LOWMEM”“ HIGHMEM”,还定义了“内核虚拟地址”“内核逻辑地址”。它们是同一件事,但名称不同。那就是软件的“美”,它是如此依赖于描述语言。
史蒂夫

Answers:


69

在32位架构上,用于寻址RAM的地址空间范围是:

0x00000000 - 0xffffffff

4'294'967'295(4 GB)。

linux内核将3/1(也可以是2/2,或1/3 1)分别划分为用户空间(高内存)和内核空间(低内存)。

用户空间范围:

0x00000000 - 0xbfffffff

每个新产生的用户进程都会在该区域内获得一个地址(范围)。用户进程通常是不受信任的,因此被禁止访问内核空间。此外,它们被认为是非紧急的,通常情况下,内核会尝试将内存分配推迟到那些进程。

内核空间范围:

0xc0000000 - 0xffffffff

内核进程在此处获取其地址(范围)。内核可以直接访问此1 GB地址(嗯,不是完整的1 GB地址,有128 MB保留用于高内存访问)。

内核空间中产生的进程是受信任的,紧急的并且假定没有错误,内存请求被即时处理。

每个内核进程也可以根据需要访问用户空间范围。为了实现这一点,内核将地址从用户空间(高内存)映射到其内核空间(低内存),上面提到的128 MB专门为此保留。


1拆分是3 / 1、2 / 2还是1/3,由CONFIG_VMSPLIT_...选项控制;您可能可以在下面查看/boot/config*以查看为内核选择了哪个选项。


这是旧的,我不确定你在附近。但是我想问一件事:内核空间中保留的128MB(用于高内存访问),这是用户空间存储区的所有引用吗?因此,内核进程可以通过参考该区域来访问任何用户空间,对吗?
Amumu

1
为什么总是以1/4为单位?即为什么不能将其拆分为5/1或其他?
mgalgs 2012年

“可以直接访问”在这里到底是什么意思?我的意思是,内核本身不是通过虚拟内存机制访问的吗?
telenn 2012年

1
我相信您对高/低内存的说法是错误的:我相信在纯32位系统中,内核可以直接访问完整的3GB用户空间(内核可以访问内核空间和用户空间)。但是,当您拥有PAE内核时,事情变得更加复杂,现在您拥有超过3GB的RAM,每个进程可以为3GB,并且您无法直接访问整个用户空间。这是高内存和内核空间中128MB内存进入的地方。有了64位内核,它又变得更简单了,没有麻烦了,因为所有用户空间都可以从内核访问。
ctrl-alt-delor 2014年

2
@mgalgs¼,2/4和¾只是公开的一组默认选项。从2007年开始,您还可以选择5/16分和15/32分。如果您知道编辑哪条#define行,则可以自己选择几乎任意的分割。
约根森

28

首先要参考的是Linux设备驱动程序(可在线获得,也可以以书本形式获得),特别是第15章,其中有关于该主题的部分。

在理想的情况下,每个系统组件都将能够映射它需要访问的所有内存。Linux和大多数操作系统上的进程就是这种情况:32位进程只能访问少于2 ^ 32字节的虚拟内存(实际上,在典型的Linux 32位体系结构上约为3GB)。内核变得困难,内核需要能够映射正在执行其系统调用的进程的完整内存,整个物理内存以及任何其他内存映射的硬件设备。

因此,当32位内核需要映射超过4GB的内存时,必须在高内存支持下进行编译。高内存是指未永久映射到内核地址空间中的内存。(低内存是相反的:它总是被映射的,因此您只需在内核中取消引用指针就可以访问它。)

当您从内核代码访问高内存时,您需要kmap首先进行调用,以从页面数据结构(struct page)获取指针。kmap无论页面是在高内存还是低内存中,调用均有效。还有一些kmap_atomic增加了约束,但是在多处理器计算机上效率更高,因为它使用了更细粒度的锁定。通过获得的指针kmap是一种资源:它占用了地址空间。完成后,您必须调用kunmap(或kunmap_atomic)释放该资源。则指针将不再有效,并且直到kmap再次调用该页面的内容才能被访问。


2
感谢Gilles的回答。但是,我仍然无法理解整个概念。您能否在不减少其中信息的情况下更简单一些?

17

这与Linux内核有关;我不确定任何Unix内核如何处理此问题。

高内存是用户空间程序可以寻址的内存段。它无法触摸内存不足。

低内存是Linux内核可以直接寻址的内存段。如果内核必须访问高级内存,则必须首先将其映射到其自己的地址空间。

最近引入了一个补丁,可让您控制段的位置。折衷方案是可以从用户空间中移走可寻址的内存,以便内核可以拥有更多的内存,在使用之前,这些内存不必映射。

其他资源:


4

HIGHMEM是内核内存空间的范围,但是它不是您访问的内存,而是您放置要访问的内容的地方。

典型的32位Linux虚拟内存映射如下:

  • 0x00000000-0xbfffffff:用户进程(3GB)

  • 0xc0000000-0xffffffff:内核空间(1GB)

(特定于CPU的向量以及此处忽略的所有内容)。

Linux将1GB内核空间分为LOWMEM和HIGHMEM两部分。拆分因安装而异。

如果安装为LOW和HIGH内存选择了512MB-512MB,则512MB LOWMEM(0xc0000000-0xdfffffff)在内核引导时静态映射;否则,该映射将自动生成。通常,物理内存的前几个字节用于此目的,因此该范围内的虚拟和物理地址的常量偏移量为0xc0000000。

另一方面,后者的512MB(HIGHMEM)没有静态映射(尽管您可以将页面半永久地保留在那里,但是您必须在驱动程序代码中明确地这样做)。相反,页面会在此处临时映射和取消映射,因此该范围内的虚拟和物理地址没有一致的映射。HIGHMEM的典型用途包括单次数据缓冲区。


3

据我所知,“高内存”用于应用程序空间,“低内存”用于内核。

优点是(用户空间)应用程序无法访问内核空间内存。


0

许多人说低内存是用于操作系统的。这通常是正确的,但并非必须如此。高内存和低内存只是内存空间的两个部分,但是在Linux系统中,低内存仅用于内核,高内存用于用户进程。

根据《恐龙书(操作系统概念)》,我们可以将操作系统放置在低内存或高内存中。影响此决定的主要因素是中断向量的位置。由于中断向量通常位于低内存中,因此程序员通常也将操作系统也置于低内存中。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.