今天要来讲讲linux内核中的SPARSEMEM。为什么要讲这个呢? 因为现在的内核默认开启了这个模式。
比如在arch/x86/Kconfig中可以看到如下的配置。
config ARCH_SPARSEMEM_ENABLE
def_bool y
depends on X86_64 || NUMA || X86_32 || X86_32_NON_STANDARD
select SPARSEMEM_STATIC if X86_32
select SPARSEMEM_VMEMMAP_ENABLE if X86_64
也就是只要是满足depends on这四个条件之一,默认都会开启SPARSEMEM。
你说这个理由实在有点扯淡,那好吧,说个正经点的理由。
书接上回,我们提出了一个思考题:page结构体究竟是存放在哪里?是的,这篇文章和这个问题相关~另外前文那张经典的数据结构关系图中一个未露面的成员zone_mem_map在本文中将会出现。不过我才那张图有点老,出现的可能是他的孙子辈吧。
这个东西说难其实也不难。刚开始理解时略有些麻烦,但是看明白之后也没有太多内容。就让我给你一一道来。
有啥好处?
先来说说用它的好处,否则大家都不知道这是干啥的。在原始补丁中,作者做了些比较详细的描述。我列举一下:
- 对于有内存空洞的设备,减少系统struct page使用的内存
- 内存热插拔系统需要使用
- 在NUMA系统上支持内存的overlap
后两者究竟是怎么用的,暂时还不清楚。减少系统struct page使用的内存,那是肯定的。因为在最原始的实现中,系统struct page是一个超大的静态数组。不管对应的物理地址是否有内存存在,都会有对应的struct page对应。而使用了SPARSEMEM后,只有有效的page才会有对应的struct page存在。
在减少内存使用的同时,也带来了一个问题。
- pfn_to_page()计算会比原来的慢
针对这点,内核中又引入了SPARSEMEM_VMEMMAP。这个以后再来讲解,这次先关注SPARSEMEM本身。
实现思想
SPARSEMEM提出了一个新的概念
section。
这个section就是比page更大一些的内存区域,但是呢一般意义上又比node的范围要小些。比如在x86_64平台上,这个的大小就是(2^27) = 128M。
整个系统