linux内核源码分析之页表
Posted 为了维护世界和平_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux内核源码分析之页表相关的知识,希望对你有一定的参考价值。
目录
页表用来把虚拟页映射到物理页,并且存放页的保护单位,即访问权限。
页表说明
5级页表如下
1)页全局目录(Page Global Directory,PGD)
2) 页四级目录(Page 4th Directory,P4D)
3)页上册目录(Page Upper Directory,PUD)
4)页中间目录(Page Middle Directory,PMD)
5)直接页表(Page Table ,PT)
各处理器架构可以选择使用五级,四级,三级,两级页表。同一处理器架构在页长度不同的情况下可能选择不同的页表级数。配置页表级数,内核中宏CONFIG_PGTABLE_LEVELS,一般使用默认值。
每个进程有独立的页表,进程的mm_struct实例的成员pgd指向全局目录,前面四级的页表项存放下一级页表的起始地址,直接地址的页表项存放帧号(Page Frame Number PFN)。
虚拟地址被分解为6部分:全局目录索引,页四级目录索引,页上层目录索引,页中间目录索引,直接页表索引和业内偏移。
虚拟地址转换为物理地址过程
查询页表,把虚拟地址映射为物理地址
1)根据全局目录的起始地址和页全局目录索引得到页全局目录表项的地址,然后从页表项得到四级目录的起始地址。以此类推得到直接页表的起始地址。
2)根据直接页表的起始地址和直接页表的索引得到页表项的地址,然后得到页帧号。
3)把页帧号和页内偏移组合成物理地址。
内核中的宏以及说明
内核定义了各级页表索引在虚拟地址中的偏移
PAGE_SHIFT | 页内偏移位数 |
PMD_SHIFT | 页中间目录索引的偏移 |
PUD_SHIFT | 页上层目录索引的偏移 |
P4D_SHIFT | 页四级目录索引的偏移 |
PGDIR_SHIFT | 页全局索引的偏移 |
定义了各级页表表项描述的地址空间大小
PAGE_SIZE | 直接页表项映射的地址空间的大小,单位页长度 |
PMD_SIZE | 页中间目录表项映射的地址空间大小 |
PUD_SIZE | 页上层目录表项映射地址空间大小 |
P4D_SIZE | 页4级目录表项映射地址空间大小 |
PGDIR_SIZE | 全局目录表项映射地址空间大小 |
各级页表存放指针个数以及页的阶数
PTRS_PER_PGD | 全局目录的表项数据 | PGD_ORDER | 全局目录页阶 |
PTR_PER_P4D | 页四级目录的表项数量 | P4D_ORDER | 四级目录页阶 |
PTR_PER_PUD | 页上层目录的表项数量 | PUD_ORDER | 上层目录页阶 |
PTR_PER_PMD | 页中间目录的表项数量 | PMD_ORDER | 中间目录页阶 |
PTR_PER_PTE | 直接页表的表项数量 | PTE_ORDER | 直接页表阶数 |
typdef struct unsigned long pgd;pgd_t;
内核定义了宏和内联函数,以全局目录为例
//宏pgd_val()用来把pgd_t类型转化换成无符号整数
#define pgd_val(x) ((x).pgd)
//宏__pgd()用来把无符号长整数转化为pgd_t类型
#define __pgd(x) ((pgd_t)) (x) )
//宏pgd_index(address)用来从虚拟地址分解除页全局目录索引
#define pgd_index(address)((address)>>PGDIR_SHIFT) & (PTRS_PER_PGD - 1)
//宏pgd_offset(mm,addr)用来返回指定进程的虚拟地址对应的页全局目录表项的地址
#define pgd_offset_k(address) pgd_offset(&init_mm,address)
//内联函数pgd_none(pgd)用来判断页全局目录表项是空表项,空表项没有指向下一级
//内联函数pgd_present(pgd)用来判断页全局目录表项是否存在,即是否指向下一级页表
大多数处理器支持的最小页长度是4KB
参考链接
https://course.0voice.com/v1/course/intro?courseId=2&agentId=0
以上是关于linux内核源码分析之页表的主要内容,如果未能解决你的问题,请参考以下文章