内存管理

页框管理

  • Linux采用4KB页框大小作为标准内存分配单元
  • 页描述符

    • 描述页框的信息
    • 页描述符字段
      • _count: 页的引用计数器,该字段为-1标示页框空闲
      • flags: 描述页框状态的标志
  • 非一致内存访问(NUMA)

    • 不同CPU访问页面所需的时间不一样
    • 对于每个CPU,内核试图把耗时节点的访问次数捡到最少
  • 内存管理区

    • 80x86硬件的约束

      • DMA 只能对RAM的前16MB进行寻址
      • 线性地址空间太小,CPU不能直接访问所有的物理内存
    • 3个内存管理区

      • ZONE_DMA: 包含低于16MB的内存页框
      • ZONE_NORMAL: 包含16MB且低于896MB的内存页框
      • ZONE_HIGHMEM: 高于896MB的页框
    • 保留的页框池

      • 减少内存分配失败情况的发生
      • 保留内存
    • 分区页框分配器

      • 处理对连续页框组的内存分配请求
    • 高端内存页框的内核映射

      • 永久内核映射
        • 可能阻塞当前进程,不能用于中断处理程序和可延迟函数
      • 临时内核映射
        • 不是阻塞当前进程
        • 只有很少的临时内核映射可以同时建立
      • 非连续内存分配
    • 伙伴系统算法

      • 解决外碎片问题:尽管有足够的空闲页框满足要求,但是无法满足分配一块大的连续页框
      • 本质上避免外碎片的方法

        • 利用分页单元把一组非连续的空闲页框映射到连续的线性地址空间
        • 记录现有的页框分块情况,避免为满足小块的请求而分割打的空闲块
      • 伙伴算法

        • 所有空闲页框分组,为11个块链表
        • 每个链表分表包含大小为1,2,4,8,16,32,64,128,256,512和1024个连续的页框
      • 数据结构
        • 分配块:__rmqueue函数实现(P314)
        • 释放块:__free_pages_bulk函数实现(P315)
    • 每个CPU页框高速缓存

      • 包含一些预分配的页框,满足本地CPU发出的单一内存请求

内存区管理

  • 高速缓存描述符和slab描述符

  • 普通和专用高速缓存

    • 普通高速缓存:只由slab分配器用于自己的目的
    • 专用高速缓存:由内核其余部分使用
  • 对象描述符

  • slab对象的分配和释放(P337)

  • 内存池

    • 动态内存的储备,只能被特定的内核成分使用

非连续内存区管理

  • 完全避免外碎片,但需要打乱内核页表
  • 非连续内存区的描述符
  • 非连续内存区的分配和释放(P345)