本文所述关于内存管理的系列文章主要是对陈莉君老师所讲述的内存管理知识讲座的整理。前端
本讲座主要分三个主题展开对内存管理进行讲解:内存管理的硬件基础、虚拟地址空间的管理、物理地址空间的管理.node
本文将主要以X86架构为例来介绍伙伴算法和slab分配算法
Linux的伙伴算法将全部的空闲页面分红MAX_ORDER+1(MAX_ORDER默认大小为11)个块链表数组
每一个链表中的一个节点指向一个含有2的幂次个页面的块,即页块或简称块缓存
图 伙伴算法结构实例图数据结构
0:每一个页块的大小为1个页架构
1:每一个页块的大小为2个页函数
。。。性能
MAX_ORDER:每一个页块的大小为2的MAX_ORDER次方个页3d
大小相同、物理地址连续的两个页块称为伙伴
首先在大小知足要求的块链表中查找是否有空闲块,如有则直接分配,不然在更大的块的块链表中查找;
逆过程是块的释放,此时会把知足伙伴关系的块合并,组成一个更大的块,并插入到相应的块链表中
每一个页框对应一个struct page实例
每一个内存区关联一个struct zone区域,该结构中用free_area数组对空闲页框进行管理
负责大块连续物理内存的分配和释放,以页框为基本单位,避免外部碎片
负责小块物理内存的分配,而且它也做为一个缓存,主要针对内核中常常分配并释放的对象
内核常常请求和释放单个页框,该缓存包含预先分配的页框,用于知足本地CPU发出的单一页框请求
若是分配阶为i的页框块,那么先从第i条页框块链表中查找是否存在这么大小的空闲块。若是有则分配,不然在第i+1条链表中继续查找,直到找到为止
若是申请大小为8个(分配阶为3)页的页块,但却在页块大小为32(分配阶为5)的链表中找到空闲块,则先将这32个页面对半等分,前一半做为分配使用,另外一半做为新元素插入下级大小为16(分配阶为4)的链表中;
继续将前一半大小为16的页块等分,一半分配,另外一半插入大小为8(分配阶为3)的链表中
5节描述的伙伴算法经过__rmqueue()主要调用以下两个函数:
在指定的内存分配区上,从说请求分配阶order对应的链表开始查找所需大小的空闲块,若是不成功者从高一阶的链表上继续查找
若是所获得的内存块大于说请求的内存块,则按照伙伴算法的分配原理将大的页框块分裂为小的页框块
基于伙伴算法、每CPU高速缓存和slab高速缓存造成两种内存分配器
处理对连续页框的内存分配请求。分区页框分配器分为两大部分:前端的管理区分配器和伙伴系统
管理区分配器负责搜索一个能知足请求页框大小的管理区;
在每一个管理区中,具体的页框分配工做由伙伴系统负责,为了达到更好的性能,单个页框的申请直接由每cpu页框高速缓存完成
图 分区页框分配器示例图
将各类分配对象分区放进高速缓存,即每一个高速缓存都对同类型分配对象的一种“储备”
图 页框分配函数的关系
进程调用malloc()->
得到一块虚拟内存->
内存访问,若是还未分配物理内存->
发生缺页异常->
内核调用__alloc_pages为进程分配物理页框,并将物理内存和虚拟内存的映射关系写入页表