本文出现的内核代码来自linux4.19,如果有兴趣,读者可以配合代码阅读本文 。
一、Linux物理内存外碎片化概述
什么是Linux物理内存碎片化?Linux物理内存碎片化包括两种:
1.物理内存内碎片:指分配给用户的内存空间中未被使用的部分 。
例如进程需要使用3K bytes物理内存,于是向系统申请了大小等于3Kbytes的内存,但是由于Linux内核伙伴系统算法最小颗粒是4K bytes,所以分配的是4Kbytes内存,那么其中1K bytes未被使用的内存就是内存内碎片 。
文章插图
Linux物理内存内碎片
2.物理内存外碎片化:指系统中无法利用的小内存块 。
例如系统剩余内存为16K bytes,但是这16K bytes内存是由4个4K bytes的页面组成,即16K内存物理页帧号#1不连续 。在系统剩余16K bytes内存的情况下,系统却无法成功分配大于4K的连续物理内存,该情况就是内存外碎片导致,本文中阐述的就是物理内存外碎片化 。
注:#1物理页帧号:Linux物理内存是通过页面进行管理,并对每个页面进行编号,称为页帧号,如果是连续的两个物理页面,其页帧号是连续的 。
文章插图
Linux物理内存外碎片
二、Linux物理内存管理框架
阐述物理内存外碎片化的来龙去脉前,先得明白Linux是如何管理物理内存的?Linux内核采用的是buddy system allocation,即著名的伙伴系统分配器 。
1.设计思路
伙伴系统分配器的核心思路:将系统的空闲页面分为11个块链表,每个块链表分别管理着1,2,4,8,16,32,64,128,256,512和1024个物理页帧号连续的页面 。每个页面大小为4K bytes,buddy管理的块大小范围从4K bytes到4M bytes,以2的倍数递增 。
文章插图
Linux物理内存管理框架图
2.管理逻辑
Linux对物理页面管理的框架如上图,由于本文阐述的是物理内存外碎片,所以关于伙伴系统本文只做简单分析,不涉及具体的细节并不阐述关于per cpu pageset等内容,如果读者有兴趣,可以参考内核源码 。
Linux将物理内存分为不同的node和zone来管理:
- node:为了支持NUMA结构,即CPU对不同内存簇的访问速度不同,Linux设计了node结构,将物理内存分为多个内存节点管理;对于UMA结构,只有一个node节点 。
- zone:为兼容不同的平台的硬件限制,例如80x86的体系结构的硬件总线访问等问题,Linux将node节点下的内存分为多个zone;目前在ARM平台,多个zone管理已非必要 。
文章插图
free_area数组总共有11个索引,每个索引管理着不同大小的块链表 。
- free_area[0]管理的内存单位为2^0页面,即4K byte内存;
- free_area[1]管理的内存单位为2^1的物理页帧号连续页面,即8K bytes内存;
- 以此类推;
文章插图
当分配页面时,伙伴系统拿页面的步骤如下:(不考虑内存慢速路径)
- 根据分配页面类型,找到对应的内存节点node和内存管理单元zone;
- 根据分配页面大小,找到的对应大小的free_area结构体;
- 根据分配页面类型,找到对应的free_list链表,分配页面;
- 根据分配页面类型,找到对应的内存节点node和内存管理单元zone;
- 判断是否有物理页帧号相连的空闲内存块,可以跟被释放的内存块合并成更大的块内存,合并的条件:
- 物理帧必须都是连续的;
- 相同的类型和相同的大小;
- 合并后块内存的第一个页面的物理地址满足”2*块大小*4K”的倍数 。
- 根据释放页面的大小或者合并的大小,找到的对应大小的free_area结构体;
- 根据释放页面的类型,找到对应的free_list链表,释放页面;
从“二、Linux物理内存管理架构”,可以发现伙伴系统内存管理框架是可以有效改善物理内存外碎片的,因为伙伴系统有如下两个管理逻辑,可以减少了外碎片化的产生:
推荐阅读
- 老电脑升级加固态硬盘还是内存、CPU、显卡?旧电脑升级硬件建议
- linux中tcpdump的详细用法
- Linux 建立本地yum源
- 网络防御-防火墙设置IP网段规则
- 同样的内核,为什么linux干净稳定,而android臃肿又乌烟瘴气?
- RedHat Linux系统U盘安装图文教程
- 科普|物理学家在水下开枪“自杀”:把科学作S玩明白了
- linux入门命令详解
- Linux第8课:Redirection的4类7种方法,实现文件的呼叫转移
- 学习 Shell 脚本编程的免费资源 | Linux 中国