LWN:high memory的末日快到了?

本文探讨了Linux内核中的高内存机制,一种用于解决32位系统中物理内存大小限制的技术。随着64位系统普及,高内存的使用逐渐减少,引发了关于其在现代系统中角色的讨论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关注了就能看到更多这么棒的文章哦~

An end to high memory?

By Jonathan Corbet
February 27, 2020

原文来自:https://lwn.net/Articles/813201/

Johannes Weiner提出了一个patch([PATCH] vfs: keep inodes with page cache off the inode shrinker LRU),可以直接改善memory回收的效率。没有这个patch的话,虚拟文件系统层(virtual filesystem layer)会把memory-management subsystem认为可能还有用的一些memory直接丢弃。不过这个patch很不巧地跟一个很久很久以前的功能产生了冲突,这个功能就是“high memory”。它已经有20多年的历史了,目前high memory已经很少有人用了,开发者们也认为应该从kernel中慢慢移除。

A high-memory refresher

年轻的读者可能都还不知道什么是high memory。这里我们先回顾一下。首先也要跟我们读者接触电脑最久的那些人明确一下,这个high memory跟早期PC上的哪个"high memory"并不是一回事。早期PC上的high memory是指位于640KB这里的一块硬件实现中的内存空洞,这个来源应该归功于Bill Gates。而我们所说的Linux kernel中的high memory,则是一个软件结构,而不是指那个硬件概念。

kernel从最开始的时候就一直维护着一个“direct map”,就是把所有的物理内存直接在kernel space映射成为一个线性数组一样的一大块区域。kernel利用这个direct map,可以轻松操作系统中的任何一个page。同时,这种做法在现代的硬件上也有效率优势,因为可以利用huge page来做映射了。

不过,随着memory size的增长,就出现了一个问题。32-bit系统上可以对4GB的虚拟内存空间进行寻址,而user space和kernel如果有各自独立的4GB地址空间,这样一来因为需要频繁进行TLB flush,就会导致明显的性能损失。为了避免这些浪费,Linux就对kernel和user mode共享了地址空间,只是通过内存保护属性来确保user space无法访问kernel的内存(尽管其实是在同一个公共地址空间)。这种做法节省了许多CPU时间,不过随着Meltdown漏洞出现之后,kernel地址空间不得不开始独立开来,这是后话了。

kernel对4GB虚拟地址空间的分配,在缺省情况下是这样的:3GB空间分配给user space,最顶端的1GB留给kernel自己。1GB对Kernel本身绰绰有余,哪怕5.x系列的kernel也比1GB药效。不过系统的direct memory map的大小(等同于系统中所具有的所有物理内存的大小),也需要放在这个区域中。早期的kernel只可以操作那些direct map的内存,因此在许多年以前Linux系统只能直接使用不超过1GB的物理内存。这种模式保持了很长很长时间,哪怕那些相当大的服务器系统也没有超出这个限制。

不过,最终人们发现,在64位系统普及之前,就已经有许多需求要再现有系统上支持更大的物理memory size了,所以我们不得不先做些工作。既然direct map无法放下所有物理内存,那么就放弃这个需求好了,改为只是尽量多映射一些memory进来,毕竟可用的地址空间有限。没能映射进来的memory就被称为“high memory”。这里的分界线完全取决于kernel configuration,以及有多少地址空间是专供kernel使用的,而不是取决于硬件配置。

high memory给direct map里直接映射的memory还是很相像的:可以被map到user space,使用者看不出任何区别。不过既然它不在direct map之内,也就意味着kernel无法直接访问它,而是必须要临时创建一个single-page的mapping映射关系再访问,这种方法还是有些额外耗时。这就意味着,high memory不能放任何kernel需要能快速访问的内容,具体来说,任何kernel data structure都不可以放在high memory,而是要放在low memory。所以low memory在许多系统上就变成了一个需要争抢的稀有资源。

64位系统则不受4GB虚拟地址空间的限制,所以完全不需要high memory这套方案。不过32位系统上都需要使用high memory,kernel代码里面到处都有high memory相关的处理迹象。举例来说,在所有调用kmap()和kmap_atomic()的函数里,针对64位系统什么都不需要做,但是在小型系统上则要访问high memory。直到今天,high memory有时候还是会影响一些开发决策。

Inode-cache shrinking vs. highmem

在Linux系统上访问某个文件的时候,kernel会先加载一个对应这个文件的inode structure。这些inode结构都在缓存(cache)中,因为访问过一次的文件很可能需要在近期进行频繁访问。跟这个文件相关的数据页也会随着这个访问被缓存到page cache中,并跟cached inode关联起来。当然这两种cache都不能毫无限制地增长,因此memory-management system会在内存很紧张的时候从这两种cache中移除数据。针对inode cache这种缓存,这种操作是通过虚拟文件系统层提供的"shrinker"函数来完成的。

在Weiner的patch描述信息中,他指出inode-cache shrinker有权把那些在page cache中有关联page的inode从inode cache中移除。这样就会导致这些关联page也被回收了。做这种操作的时候,inode-cache shrinker无法知道相关的这些page是正在被使用与否。因此他认为此前的行为不是很合理:

This behavior of invalidating page cache from the inode shrinker goes back to even before the git import of the kernel tree. It may have been less noticeable when the VM itself didn't have real workingset protection, and floods of one-off cache would push out any active cache over time anyway. But the VM has come a long way since then and the inode shrinker is now actively subverting its caching strategy.

Andrew Morton此前实现成这样的时候,主要是因为high memory的缘故。Inode是kernel data structure,需要存放在low memory区域;而page-cache page则可以放在high memory区域。如果在page cache中存在的一些page能阻止inode structure的回收,那么就意味着了high-memory中的几个page会阻止珍贵的low memory空间的回收。在使用了high memory的系统上,如果能回收几百byte的low memory,那么可能就值得牺牲cache中的许多page内容。Morton认为这种做法是很合理的,现在也应该保持:“a 7GB highmem machine isn't crazy and I expect the inode has become larger since those days”

讨论来回了几个回合,Linus Torvalds跳出来插了一句:“in the intervening years a 7GB highmem machine has indeed become crazy”。他认为high memory应该改为deprecated状态了:“In this day and age, there is no excuse for running a 32-bit kernel with lots of physical memory”。其他人也很快表示支持这种看法。移除high-memory就能大大简化memory-management代码,并且在多数人使用的64位系统上只有好处没有坏处。

不过,并不是所有系统都有64位CPU的。尤其是Arm架构,目前仍然有许多32位CPU在设计、生产、使用中。Russel King指出,有许多在售的32位Arm系统都带着超过1GB的memory:“You're probably talking about crippling support for any 32-bit ARM system produced in the last 8 to 10 years”。

Arnd Bergmann则更详细地介绍了32位Arm系统的现状。其中有一款市场上着力推广的TI CPU就能够处理8GB的RAM。不过他也说许多基于Arm的设备上其实安装的memory都小得多,因为超过512MB的memory就太贵了。目前有些手机是有2GB的memory的,仍然需要支持,不过这些设备其实可以不依赖high memory,而是直接把kernel这部分地址空间增大到2GB即可。也是有更大内存的系统的,不过拥有3GB或更多内存的系统非常少。当然,少并不等于不存在。

讨论还没有达成实质性的结论。我读过这些讨论之后得出的结论是,虽然要想deprecate high memory还太早,不过在今后几年中high memory会面对更多的压力。同时,人们不会在high-memory系统上分析性能情况来强行要求什么。Weiner的patch也准备了第二版,会在拥有high memory的系统上保持原有的行为不变。所以对那些仍然需要high memory的系统来说,它们还是安全的,至少现在是安全的。

全文完

LWN文章遵循CC BY-SA 4.0许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注LWN深度文章以及开源社区的各种新近言论~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值