判断某个页框pfn是否有效(section和root)

来源:互联网 发布:ueditor java图片上传 编辑:程序博客网 时间:2024/06/06 00:13

前言

在一些系统中,物理地址空间存在许多的空洞——无效区域
内核需要管理有效区域,只为或尽量只为有效区域中的页框建立page结构,避免物理内存的浪费

如何管理有效区域?

  • 以页框为粒度?如位向量、…………
    空间复杂度同页框(无效+有效)个数线性相关,扩展性差
  • 以若干长度不等的有效或空洞区域为粒度?如线段树、…………
    时间复杂度差,和有效区域个数成log关系

Linux内核以section为粒度

时间和空间的折中,并牺牲了一定的准确性,理论上

Linux内核将物理地址空间划分成若干个section

  • 每个section大小一样,拥有PAGES_PER_SECTION(0x8000)个页框,即128MB
  • 物理地址划分:
    • bit0—bit11:页内字节偏移量
    • bit12—bit26:section内的页框偏移量
    • bit12—bit45:页框号
    • bit27—bit45:section号
    • 共计NR_MEM_SECTIONS(0x80000)个section
  • 内核使用mem_section描述一个section
struct mem_section {    unsigned long section_mem_map;    //当前section内,所有页框对应的page结构数组的起始线性地址    unsigned long *pageblock_flags;    //指向一段空间,存放了当前section内所有页框的迁移等属性};

section_mem_map包括两个部分
- 当前section内,所有页框对应的page结构数组的起始线性地址
- 标志位:

  • SECTION_MARKED_PRESENT:bit0
  • SECTION_HAS_MEM_MAP:bit1

每个section,都有一个mem_section结构,内核如何组织这些结构?同page结构一样,由于空洞的存在,一些section或者连续的section是无效的,不必创建。

root

每SECTIONS_PER_ROOT(0x80)个section,组织成一个root
一个root包含0x400000个页框,共16GB

物理地址划分:
- bit27—bit33:root内section的偏移量
- bit34—bit45:root号
- 共计NR_MEM_SECTIONS(0x80000)个section
- 共计NR_SECTION_ROOTS(0x1000)个root

内核没有提供专门的元数据类型描述root
root就是mem_section结构数组
所有root的地址,都放在mem_section指针数组中
struct mem_section *mem_section[NR_SECTION_ROOTS]//全局实例

这里写图片描述

root/section的构建过程

  • 创建root空间
  • 并设置内存region对应的mem_section的section_mem_map字段的bit0( SECTION_MARKED_PRESENT )
  • 为设置了SECTION_MARKED_PRESENT位的mem_section,以node为单位:
    统计需要的page结构体总数,分配page结构体数组
    统计需要的pageblock_flags指向空间的总大小,并分配
    设置section_mem_map、pageblock_flags,并设置SECTION_HAS_MEM_MAP位

不同section的page结构、 pageblock_flags指向的空间,在同一个node内,在物理地址上是连续的。

一个node内,所有页框的page结构在物理上是连续的。这也是符合NUMA访问优化要求的。不要出现在node a上的page结构,描述的是node b上的页框

在基本的SPARSEMEM模型中,每个node都有一个mem_map数组

如何在若干个mem_map数组间,完成page结构与pfn转换?
pfn-to-page:section_mem_map的作用
page-to-pfn:page结构的flags中存储section编号

section的管理方式在理论上损失了一定正确性

一个section内,哪怕只有一个页框有效,这个section也会建立,所有page结构也会建立

SPARSEMEM_VMEMMAP

针对64位环境,线性地址空间巨大
所有的mem_map(page结构数组)被映射到连续的线性地址空间vmemmap

SPARSEMEM_EXTREME

在基本的SPARSEMEM中,root表
struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT];
空间占用量巨大

总结

  1. 通过section和root的引用,我们减少了对空洞内存page结构的创建,节省了物理内存。同时能快速知道某个page是否是有效内存。
  2. 一个section内,没有一个页框有效,这个section则不会建立,当然它在线性地址空间vmemmap的线性区间仍然保留,只是不为这段线性区间分配对应的物理内存罢了(因为不需要存放page结构)。这个道理同样也适合没有一个section有效的root。
原创粉丝点击