high memory

本文详细解释了32位Linux内核中HighMemory的概念及其必要性。介绍了如何将物理内存超过896MB的部分标记为HighMemory,并讨论了内核如何通过预留的128MB虚拟地址空间动态地访问这部分内存。

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

high memory只存在于32位kernel下,以下文字都针对32位kernel。
1)什么是high memory,为什么要有high memory
Linux人为的把4G虚拟地址空间(32位地址最多寻址4G)分为3G+1G,其中0~3G为用户程序地址空间,3G~4G为kernel地址空间(为什么要这么分?为什么用户程序和kernel不能各自独享4G虚拟地址空间?这两个问题下次再说吧,这里不表),这就是说kernel最多寻址1G的虚拟地址空间。
当CPU启用MMU的paging机制后,CPU访问的是虚拟地址,然后由MMU根据页表转换成物理地址。页表是由kernel维护的,所以kernel可以决定1G的虚拟地址空间具体映射到什么物理地址。但是kernel最多只有3G~4G这1G地址空间,所以不管kernel怎么映射,最多只能映射1G的物理内存。所以如果一个系统有超过1G的物理内存,在某一时刻,必然有一部分kernel是无法直接访问到的(这个一定要想清楚,不然无法明白high memory)。另外,kernel除了访问内存外,还需要访问很多IO设备。在现在的计算机体系结构下,这些IO设备的资源(比如寄存器,片上内存等)一般都是通过MMIO的方式映射到物理内存地址空间来访问的,就是说kernel的1G地址空间除了映射内存,还要考虑到映射这些IO资源--换句话说,kernel还需要预留出一部分虚拟地址空间用来映射这些IO设备(ioremap就是干这个的)。
Linux kernel采用了最简单的映射方式来映射物理内存,即把物理地址+3G按照线性关系直接映射到kernel空间。考虑到一部分kernel虚拟地址空间需要留给IO设备(以及一些其他特殊用途),Linux kernel最多直接映射896M物理内存,而预留了最高端的128M虚拟地址空间给IO设备(还有其他的用途)。所以,当系统有大于896M内存时,超过896M的内存kernel就无法直接访问到了(想明白了么?),这部分内存就是high memory。那kernel就永远无法访问到超过896M的内存了马?不是的,kernel已经预留了128M虚拟地址,我们可以用这个地址来动态的映射到high memory,从而来访问high memory。所以预留的128M除了映射IO设备外,还有一个重要的功能是提供了一种动态访问high memory的一种手段(kmap主要就是干这个的,当然还有vmalloc)。
当然,在系统物理内存<896M,比如只有512M的时候,就没有high memory了,因为512M的物理内存都已经被kernel直接映射。事实上,在物理内存<896M时,从3G+max_phy ~ 4G的空间都作为上述的预留的内核地址空间(未考证)。
要理解high memory,关键是把物理内存管理,虚拟地址空间管理,以及两者间的映射(页表管理)三个部分分开考虑,不要把物理内存管理和虚拟地址空间管理混在一起。比如high memory也参与kernel的物理内存分配,你调用get_page得到的物理页有可能是low memory,也可以是high memory,这个物理页可以被映射到kernel,同时也可以被映射到user space。再比如vmalloc,只保证返回的虚拟地址是在预留的vmalloc area里,对应的物理内存,可以是low memory,也可以是high memory。当然出于性能考虑,kernel可能会优先分配直接映射的low memory,但我们不能假设high memory就不会被分配到。
一些结论:
1)high memory针对的是物理内存,不是虚拟内存,更确切的,虚拟地址空间。
2)high memory也是被内核管理的(有对应的page结构),只是没有映射到内核虚拟地址空间。当kernel需要分配high memory时,通过kmap等从预留的地址空间中动态分配一个地址,然后映射到high memory,从而访问这个物理页。
3)high memory和low memory一样,都是参与内核的物理内存分配,都可以被映射到kernel地址空间,也都可以被映射到user space地址空间。
4)物理内存<896M时,没有high memory,因为所有的内存都被kernel直接映射了。
5)64位系统下不会有high memory,因为64位虚拟地址空间非常大(分给kernel的也很大),完全能够直接映射全部物理内存。
2)题外话1 -- 关于最高端的128M内核虚拟地址(或者当物理内存<896M时更大)的分配:
这部分地址空间被划分为4段,分别是fixed mapping,kmap area,vmalloc area,还有8M用来catch kernel指针错误。其中fixed mapping主要用在boot阶段用来永久性映射一些物理地址固定的数据结构或者硬件地址(比如ACPI表,APIC地址,等等)。kmap area是kernel用来临时建立映射来访问物理页用的,可用的地址空间也比较小。128M中绝大部分reserve了给vmalloc area,vmalloc和ioremap返回的都是这个空间里的地址。
另外,在《Understanding the Linux Virtual Memory Manager》这本书中有linux 进程地址空间划分的详细图,很不错,我就懒得画了。
3)题外话2 -- 为什么要人为划分3G/1G?为什么kernel没有自己的4G地址空间?为什么所有进程共享kernel地址空间?
高内存利用率指的是计算机系统中内存使用率较高的情况。这意味着大量可用内存被使用,可能导致性能下降并可能导致系统不稳定。高内存利用率的原因可能有以下几点: 1. 内存泄漏:当程序未能释放不再使用的内存时,就会发生内存泄漏,导致内存逐渐消耗。及时发现并修复内存泄漏是很重要的,以防止高内存利用率的问题。 2. 资源密集型程序:内存密集型应用程序(如视频编辑软件、虚拟机或数据库)可能会消耗大量内存。如果同时运行多个资源密集型程序,会导致高内存使用率。 3. 内存不足:如果计算机的物理内存不足以处理工作负载,会导致高内存利用率。增加更多的内存可以帮助缓解这个问题。 4. 后台进程:在系统上运行的某些后台进程或服务可能会消耗大量内存。识别和管理这些进程可以优化内存使用。 为了解决高内存利用率,您可以尝试以下步骤: 1. 关闭不必要的程序:关闭任何未使用或不必要的应用程序以释放内存。 2. 检查内存泄漏:使用适当的工具来识别和修复应用程序中的内存泄漏。 3. 升级内存:如果系统内存不足,考虑升级内存以更有效地处理工作负载。 4. 监控后台进程:识别资源密集型的后台进程,并考虑其是否必要。您可能需要禁用或优化它们。 5. 重新启动计算机:简单地重新启动可以清除任何临时内存问题,降低内存利用率。 请记住,解决高内存利用率的具体步骤可能会因操作系统和所使用的程序而有所不同。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值