linux 内核内存管理办法简介(上)

 本文从页的分配管理上进行阐述(内存管理区,每CPU页高速缓存和伙伴系统),下篇文章阐述页内空间的分配管理(slab分配器,通用和专用高速缓存)。
     
     1、内存管理区
     linux操作系统把内存节点的物理内存划分为三个管理区,分别为:ZONE_DMA,包含低于16MB的内存页框;ZONE_NORMAL,包含16MB---896MB的内存页框;ZONE_HIGHMEM,高端内存,包含从896MB开始以上的内存页框。
     对于32位操作系统,ZONE_DMA 和ZONE_NORMAL为内核可以直接访问的地址空间,在进程线性地址空间中,通常被映射到第4个GB。ZONE_HIGHMEM为内核不能直接访问的,可以通过“高端内存页框的内核映射”进行访问,包括建立永久性的内核映射和临时内核映射(各有优缺点)两种。对于64位操作系统而言,不存在ZONE_HIGHMEM区,也就是说内核可以访问所有的页框。
     
     这三个内存区,分别由各自的内存管理区进行管理,管理区分配器进行所有内存区的管理,如下图所示。
linux 内核内存管理办法简介(上)_第1张图片

     这里要注意的是,每个内存管理区会保存一定的内存页框,叫做“ 保留的页框池”, 用于满足中断处理程序或内部临界区发出的原子分配请求。保留页框池的大小由管理区的大小,这个值同时影响到了页框回收的阈值,这里就不多说明。

     1.1 伙伴系统算法
     linux操作系统采用伙伴系统进行页框的管理。把所有的空闲页框分组为11个块链表,每个块链表分别包含大小为1,2,4,......512和1024个连续的页框, 每个块的第一个页框的物理地址是该块大小的整数倍,如大小为16的页框,起始地址为16*4096 的整数倍。如下如所示。
linux 内核内存管理办法简介(上)_第2张图片
图2 伙伴系统数组与页框之间的关系
linux 内核内存管理办法简介(上)_第3张图片

图3 页框分配过程,数组调整示意图
      伙伴系统的工作原理如下:
     假设申请1M空间,即256个页框,就从数组8这个位置开始查找,如果该页框的链表不为空,就从中取出一个空闲块,更新指针,返回。如果该页框的链表为空,就会查找数组的下一个,即小标为9的那一项。如果有可用的块,就将整个块分为两半,一半链接在数组下标为8的数组项,另一半返回给应用程序。依次类推,直到数组的最后一个,如果还不能满足请求,就发送出错信号,申请页框失败。
     这个过程的逆过程,就是页框释放的过程,这里不多说,值得注意的是,并不是相邻的,大小相等的两块就能合并,如大小为16的页框,起始物理地址为16*4096*3 和16*4096*4,这两个虽然连续,但并不能合并,因为他们合并后不能满足大小为32的页框的要求(见上面红色加粗本分),也即不属于大小为32页框的块。
     对于伙伴系统设计的细节,各个变量如何赋值及其特殊的意义,这里不作说明。

     1.2 每CPU页高速缓存
     linux操作系统会为每个cpu分配一个per_cpu_pages的描述符,用来存放页高速缓存中的页框数,页框数目的上界和下界等信息。
     每cpu页高速缓存的设计 ,是因为内核经常请求和释放单个页框,如果每次申请都从伙伴系统获得的话,效率很低。为了提升性能,操作系统就为每个cpu预先分配一些页框,用于单个页框申请和释放(这里注意, 如果申请或释放的页框数目不是1,就会调用伙伴系统申请或释放)。
     当每cpu页框少于一定数目时,就会向伙伴系统申请多个(per_cpu_pages中的batch决定)页框,同样的,如果每cpu页框多余一定数目,就释放一些页框到伙伴系统。 
     
     2、页内的内存管理(slab分配器)
     <未完待续>

你可能感兴趣的:(linux 内核内存管理办法简介(上))