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


为什么会有这样的区别?
这样做有什么好处?
每个都有?


评论

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

#1 楼

在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保留用于高内存访问)。 -free,将立即处理内存请求。

每个内核进程都可以访问用户空间范围(如果需要)。为此,内核将地址从用户空间(高内存)映射到其内核空间(低内存),上面提到的128 MB专为此保留。


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

评论


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

– Amumu
2012年7月2日在4:37

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

– mgalgs
2012年8月29日23:48

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

–telenn
2012年10月8日13:07



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

–ctrl-alt-delor
2014年12月2日在22:00

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

–jørgensen
15年7月28日在15:13

#2 楼

首先要参考的是Linux设备驱动程序(可以在线购买,也可以书本形式购买),特别是第15章,其中有一个主题。

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

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

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

评论


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

–森
2010-12-18 11:15

#3 楼

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

高级内存是用户空间程序可以寻址的内存段。它不能触摸低内存。

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

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

其他资源:


http://tldp.org/HOWTO/KernelAnalysis-HOWTO-7.html
http://linux-mm.org/HighMemory


#4 楼

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

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


0x00000000-0xbfffffff:用户进程(3GB)
0xc0000000-0xffffffff:内核空间(1GB)

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

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

如果安装选择LOW和HIGH内存为512MB-512MB,则512MB LOWMEM(0xc0000000-0xdfffffff)在内核启动时静态映射;如果安装选择为512MB-512MB,则为MEM。通常,物理内存的前几个字节用于此目的,因此该范围内的虚拟和物理地址的常量偏移量为0xc0000000。另一方面,后一个512MB( HIGHMEM)没有静态映射(尽管您可以将页面半永久地保留在那里,但是您必须在驱动程序代码中明确地这样做)。相反,页面会在此处临时映射和取消映射,因此该范围内的虚拟和物理地址没有一致的映射。 HIGHMEM的典型用途包括一次性数据缓冲区。

#5 楼

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

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

#6 楼

对于希望在Linux内核内存空间上下文中进行解释的人们,请注意高/低内存拆分有两种相互矛盾的定义(不幸的是,没有标准,必须在上下文中进行解释):


“高内存”定义为虚拟内存中内核空间的总和。这是仅内核可以访问的区域,并且包含大于或等于PAGE_OFFSET的所有虚拟地址。因此,“低内存”是指剩余地址的区域,它对应于每个用户进程可访问的用户空间内存。例如,在具有默认PAGE_OFFSET的32位x86上,这意味着高内存是任何带有ADDR的地址ADDR ≥ 0xC0000000 = PAGE_OFFSET(即1 GB更高)。
这就是为什么在Linux中,32位进程通常限制为3 GB。
请注意,不能直接配置PAGE_OFFSET,这取决于可配置的VMSPLIT_x选项(源)。
总结:在32位架构中,默认情况下,虚拟内存分为较低的3 GB(用户空间)和较高的1GB(内核空间)。
对于64位,PAGE_OFFSET是不可配置的,并且取决于有时在内核加载期间在运行时检测到的体系结构细节。
在x86_64上,PAGE_OFFSET0xffff888000000000(用于4级分页)(典型值),而0xff11000000000000是用于5级分页(源)。对于ARM64,通常为0x8000000000000000。但是请注意,如果启用了KASLR,则此值是有意无法预测的。





“高内存”定义为物理内存中无法与内核虚拟内存的其余部分连续映射。内核虚拟地址空间的一部分可以作为单个连续块映射到所谓的物理“低内存”中。为了完全理解这意味着什么,需要对Linux虚拟内存空间有更深入的了解。我建议浏览这些幻灯片。
来自幻灯片:

这种“高/低内存”拆分仅适用于安装的物理RAM大小相对较高(大于〜1 GB)的32位体系结构。否则,即当物理地址空间较小(<1 GB)或虚拟内存空间较大(64位)时,可以从内核虚拟内存空间访问整个物理空间。在这种情况下,所有物理内存都被认为是“低内存”。
最好根本不存在高内存,因为可以直接从内核访问整个物理空间,这使内存管理变得更加简单和容易。高效。当处理DMA(通常需要物理上连续的内存)时,这尤其重要。
另请参见@ gilles-so-stop-being-evil




#7 楼

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

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