Linux内存管理的演进

223 阅读4分钟

!以下内容皆为linux1.0版本之前

初始

image.png

分页管理方式。利用页目录和页表结构处理对内存的申请和释放操作

page.s仅包含内存页异常的中断处理过程,对缺页和页写保护的处理

主要分为两种情况处理

  • 由于缺页引起的页异常中断,通过调用do_no_page(error_code, address)来处理
  • 由写保护引起的页异常,此时调用页写保护处理函数do_wp_page(error_code, address)进程处理

内核页表从物理地址0x1000处开始(紧接着目录空间),共4个页表

每个页表,共1024项,每项4字节,总共占用4K字节

每个进程(除了0 1进程)的页表项都是进程被创建时由内核为其在主内存区申请得到的,每个页表项对应一页物理内存,

在0.11版本中,所有进程都是用一个页目录表,而每个进程都有自己的页表。

经过分段处理,内核代码和数据段长度是16MB,使用了4个页表,且直接位于页目录表后面,然后再经过分页机制变换,被直接一一对应的映射到16MB的物理内存上。

为了使用分页机制,一个32位的线性地址被分为三个部分,分别用来指定一个页目录项、一个页表项和对应物理内存页上的偏移地址

image.png

  • 页框地址:指定一页内存的物理起始地址
  • 存在位P: 确定一个页表项是否可以用于地址转换(如果为0且发出地址转换,则会发出缺页中断异常,即当前这个页未使用)
  • 已访问A
  • 已修改D
  • 读/写位
  • 用户/超级用户位
  • 如果U/S是0,则R/W不生效
  • 如果U/S是1
    • R/W是0,那么运行在用户层的代码就只能读页面
    • R/W是1,那么就有读写页面

一个系统中可以同时存在多个页目录表,而在某个时刻只有一个页目录表可用(由CPU寄存器CR3来确定)

优化机制

swap

当物理内存不够的时候,将部分暂未使用的内存页换到swap分区,从而释放物理内存以供其他进程使用。

在启动初期会根据swap分区大小来初始化swap缓冲区和swap哈希表。

  • 增加了swap_info结构体来记录swap区信息。
  • 增加swap_map_handle结构来表示swap条目。
  • 在页表项中多了一个SWP_TYPE字段来表示是否在swap区。

mmap

进程可以通过mmap将文件或其它对象映射到进程虚拟地址空间

实现了文件内存映射,为后续的共享内存服务奠定基础

使用场景

  • 大文件读写,通过mmap可以利用虚拟内存实现缓存和延迟读写
  • 进程间通信,通过共享内存方式更快速和低开销

实现

  • 增加新的系统调用mmap和munmap
  • 在mm目录下引入mmap.c文件实现映射管理
  • 每个内存区通过mm_struct结构表示,链入到mm_slot中
  • 通过扩展进程内存 descriptors 来表示mmap区
  • 定义全局数组mmap_page_range[]表示已映射内存区间

主要数据结构

  • mm_struct 描述一个内存区
  • pgd_t 页全局目录
  • mm_slot 所有内存区链表

接口调整

kmalloc

提供内核空间的动态内存分配功能,代替直接调用get_free_page等接口的方式,大大简化内核程序中的内存申请

使用场景

  • 内核数据结构的动态创建,如信号量、队列等
  • 设备驱动程序的内存申请
  • 临时性数据结构或缓冲区的分配

实现原理

kmalloc数组指向不同大小的内存池,内存池通过linked list组织空闲内存块

定义kmalloc数组指向每个大小分配的内存池, 使用宏SWITCH_ADDRESS_SPACE切换到内核地址空间

根据大小调用get_free_pages或get_free_page分配

用完后调用free_pages或free_page释放

vmalloc

为内核提供可以分配大于最大物理内存的连续虚拟内存区域,通过页表映射实现虚拟连续,实际物理不连续

使用场景

  • 大规模内核数据结构的动态创建,大小超过物理内存
  • 需要连续虚拟地址的大内存块
  • 映射硬件设备的内存到内核虚拟地址空间

实现原理

VMALLOC_RESERVE 记录vmalloc区信息。vm_struct 描述一块vmlloc区。vmap_area 全局的vmalloc区域。

  • 定义全局描述符VMALLOC_RESERVE记录vmalloc区信息
  • 初始化时根据物理内存调整vmalloc区大小
  • vmalloc函数申请地址,获取空闲页并更新页表
  • vfree函数释放地址,回收页表和页面