一文轻松理解Linux伙伴系统

1. 伙伴系统(Buddy System)

伙伴系统中,内存块的大小是2的order次幂个页面。Linux内核中order的最大值用MAX_ORDER-1来表示,MAX_ORDER通常是11,也就是把所有的空闲页面分组成11个内存块链表,每个内存块链表分别包括1,2,4,8,16,32,…,1024个连续的页面。1024个页面对应着4MB大小的连续物理内存。MAX_ORDER可以通过CONFIG_FORCE_MAX_ZONEORDER宏进行配置,在i.MX8MP Linux 5.15.x中,被配置为14,具体如下所示:

CONFIG_FORCE_MAX_ZONEORDER=14

连续的物理页称为页块(page block)。阶(order)是伙伴分配器的一个术语,是页的数量单位, 2的n次方个连续页称为n阶页块。满足以下条件的两个n阶页块称为伙伴(buddy):

  • 两个页块是相邻的,即物理地址是连续的。
  • 页块的第一页的物理页号必须是2的n次方的整数倍。
  • 如果合并成(n+1)阶页块,第一页的物理页号必须是2的n+1次方的整数倍。

以单页为例说明,0号页和1号页是伙伴,2号页和3号页是伙伴,1号页和2号页不是伙伴,因为1号页和2号页合并组成一阶页块,第一页的物理页号不是2的整数倍。

物理内存在Linux内核中分出几个zone来管理空闲页块。zone根据内核的配置来划分,如在i.MX8MP Linux 5.15.x中,zone分为ZONE_DMA和ZONE_NORMAL。

伙伴系统的空闲页块的管理如下图所示,zone数据结构中有一个free_area数据结构,数据结构的大小是MAX_ORDER。free_area数据结构中包含了MIGRATE_TYPES个链表,这里相当于zone中根据order的大小有0到(MAX_ORDER-1)个free_area, 每个free_area根据MIGRATE_TYPES类型有几个相应的链表。

Linux 5.15.x的内核代码如下所示:

MIGRATE_TYPES类型也定义在mmzone.h文件中,具体如下所示:

在系统长时间运行后,物理内存可能出现很多碎片,可用物理页很多,但是最大的连续物理内存可能只有一页。内存碎片对用户程序不是问题,因为用户程序可以通过页表把连续的虚拟页映射到不连续的物理页。但是内存碎片对内核是一个问题,因为内核使用直接映射的虚拟地址空间,连续的虚拟页必须映射到连续的物理页。内存碎片是伙伴分配器的一个弱点。

为了预防内存碎片,内核根据可移动性把物理页分为 3 种类型,具体如上所示。

  • 不可移动页:位置必须固定,不能移动,直接映射到内核虚拟地址空间的页属于这一类。
  • 可移动页:使用页表映射的页属于这一类,可以移动到其他位置,然后修改页表映射。
  • 可回收页:不能移动,但可以回收,需要数据的时候可以重新从数据源获取。后备存储设备支持的页属于这一类。

内核把具有相同可移动性的页分组。为什么这种方法可以减少碎片?

试想:如果不可移动页出现在可移动内存区域的中间,会阻止可移动内存区域合并。这种方法把不可移动页聚集在一起,可以防止不可移动页出现在可移动内存区域的中间。

前面3种是真正的迁移类型,后面的迁移类型都有特殊用途:MIGRATE_HIGHATOMIC用于高阶原子分配,MIGRATE_CMA用于连续内存分配器,MIGRATE_ISOLATE用来隔离物理页(由连续内存分配器、内存热插拔和从内存硬件错误恢复等功能使用)。

1.1 Linux物理内存区域

Linux内核定义的区域类型如下:

  • ZONE_DMA:如果有些设备不能直接访问所有内存,需要使用DMA区域。例如旧的工业标准体系结构(Industry Standard Architecture,ISA)总线只能直接访问16MB以下的内存。
  • ZONE_DMA32:64位系统,如果既要支持只能直接访问16MB以下内存的设备,又要支持只能直接访问4GB以下内存的32位设备,那么必须使用DMA32区域。
  • ZONE_NORMAL:直接映射到内核虚拟地址空间的内存区域,直译为“普通区域”,意译为“直接映射区域”或“线性映射区域”。内核虚拟地址和物理地址是线性映射的关系,即虚拟地址 =(物理地址 + 常量)。是否需要使用页表映射?不同处理器的实现不同,例如ARM处理器需要使用页表映射,而MIPS处理器不需要使用页表映射。
  • ZONE_HIGHMEM:这是32位时代的产物,内核和用户地址空间按1:3划分,内核地址空间只有1GB, 不能把1GB 以上的内存直接映射到内核地址空间,把不能直接映射的内存划分到高端内存区域。通常把DMA区域、DMA32区域和普通区域统称为低端内存区域。 64位系统的内核虚拟地址空间非常大,不再需要高端内存区域。
  • ZONE_MOVABLE:它是一个伪内存区域,用来防止内存碎片,后面讲反碎片技术的时候具体描述。
  • ZONE_DEVICE:为支持持久内存(persistent memory)热插拔增加的内存区域。

i.MX8MP Linux 5.15.x的内存区域如下所示:

2. Linux伙伴系统数据结构

Linux kernel伙伴系统数据结构如下图所示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值