没有合适的资源?快使用搜索试试~ 我知道了~
首页linux内存页表创建
资源详情
资源评论
资源推荐
的内存正式页表是在内核代码执行到 函数后执行 函数建
立的,这里要注意一个事情就是说,这里 函数可以正常创建内存页表的条件有
两个:
、 已初始化:即初始化物理内存各个 的各个 ,一般对于小型
嵌入式设备,不涉及多个内存就是一个 和一个 ;这部分初始化
是在 函数前面的对 所传参数的解析中完成的可在内核的
函数中加入打印信息验证;
、 全 局 变 量 的 代 码 段 首 尾 、 数 据 段 首 尾 四 个 成 员 已 初 始 化 : 在
前面有对这四个成员的初始化,它们规定了内核镜像的代码段起始、
代码段结尾、数据段起始、数据段结尾数据段结尾也是整个内核镜像的结尾,
给这四个成员赋的地址值都是在 链接脚本中规定的即虚拟地址,
界定它们的意义在于能够正确的界定内核镜像的运行需要在虚拟地址占用的空
间位置及大小,以利于其他内容在内核空间位置的确定。
函数首先调用的是 ,这个函数做的事情就是给静态全
局变量 赋值,这个变量就在本文件 定义,它的用处就是
在 函数创建映射时配置 !!" 硬件时需要; 函数里面
是完全与本 芯片自身体系结构相关的配置,我还没完全搞明白。。。后续再补充吧。
接下来调用的是 ,这个函数主要做两件事情,首先是确定本设
备物理内存的各个 各个 中到底有没有高端内存,根据是否存在高端内存决定每
个 的 成员值;然后是对于每个 的正确性进行检测;下面分别描述:
由下面代码判断每个物理内存 是否属于高端内存:
#$$%!&''()!*+,,#$-.&/0(1102
34
即:该 的物理内存起始虚拟地址大于 %!&''()!*+,或者小于 &/0(1102;
&/0(1102 是内核用户空间的交界,在这里定义为 55555555 也就是 # 普遍适用
值 6/ /;%!&''()!*+ 就定义在本文件 ,如下:
78%!&''()!*+ .%!&''()0+9#
%!&''()0+9 在 #::: 文件中定义,可见是不同
设备可以不同的,它标志着 区域的结尾在哪里,这里定义为 6/;<=>!,如下:
78%!&''()0+9&/0(1102;565555555
静态全局变量 定义在本文件 ,它是可以由用户
指定的,指示了 区域的大小,默认值为 >!,用户指定的方式是通过 中指
定“命令行”参数的 参数?3@,通过 前的 方式指定修
改内核中该变量的值,这里采用的就是默认值 >!;
用 区域的结尾6/;<=>!减去该区域的大小>!即得到了 区域的起
始,6/;<=>!#>!36/;=A5!5>555555;
所以,一个 的物理内存属于高端内存的条件是:
、 起始地址不大于 区域的起始虚拟地址;
、 起始地址不小于内核用户交界的虚拟地址;
当属于高端内存时,该 的 成员将置 。
除了界定物理内存 是否属于高端内存, 函数还对每个物理
内存 的正确性进行检测,这部分个人认为不是重点,主要注意下在存在高端内存情况
下代码中定义宏 )(+1*/B*/B!0! 情况下,若低端内存太大起始位置在 %!&''()!*+
之前,结尾位置超过 %!&''()!*+,则超过 %!&''()!*+ 的部分将被算进另一个
并且判定为高端内存。
接下来调用的是 ,它的作用是清除在内核代码执行到
之前时创建的大部分临时内存页表,这里需要对 # 内存页表的机制原理进行理解:
首先一个是,什么是内存页表,都有哪些属于内存注意这里的内存是广义上的内存,
不单单是物理内存?
具体的说,内存页表,更应该叫内存映射,对于有 !!" 的 )" 来说,)" 访问物理
内存或某个 () 硬件寄存器,所做的操作并非是直接把它们的物理地址放在 )" 的地址总
线,而是把一个虚拟地址交给 !!",如果 !!" 硬件存在这个虚拟地址对应的物理地址
这个映射关系就是需要创建的内容,也就是内存映射C,那么它就会把对应的物理地址放
在地址总线上。这样做最大的好处是,避免了软件程序直接访问一个不存在的地址导致出
现问题 ;用户程序可使用的“内存”很大。
再说哪些东西属于内存,很简单,不仅仅物理内存,所有通过 )" 地址总线连接的都
属于内存,比如 () 的硬件寄存器,这里有个方法验证这个道理,函数 是
最终创建内存映射的函数,看看它都被哪些函数调用:
map_memory_bank:这是为物理内存创建内存映射
devicemaps_init:这是为中断向量创建内存映射
iotable_init:这是为 SOC 硬件寄存器创建内存映射
就以上三个调用需求。
函数 是最终创建内存映射的函数,先不管哪些需求去调用这个函数,
先看这个函数本身:
这 个 函 数 只 需 要 一 个 参 数 . , 这 个 结 构 体 的 定 义 在 文
件 中,只有 A 个参数非常简单:
4 .虚拟地址起始.
4 .物理地址起始.
4 .长度.
4 .说明这个区间所属的域,以及是否可读、写、可高速缓存等属性,
硬件相关.
第一个参数非常好理解,虚拟地址起始;第二个参数是物理地址起始;第三个参数是
要映射的长度,最后一个比较复杂,但实际用到的往往只有 !2!0!(DE代表物理内存、
!2B*/B%0)2(D !2'(F%0)2(D代表中断向量、!290%*)0代表硬件 *( 寄存器,
实际含义和 硬件相关,指的是 !!" 不同页表的映射权限暂可先不关心。
那么给定这四个参数, 函数是怎么创建映射呢?现在必须描述一下
# 的分页机制:
6 位的 芯片的寻址能力就是 G63A/,地址范围即 5#5HHHH,如果按照 ! 大
小为单位进行映射,则 A/3A5I=.! 也就是需要 A5I= 个条目,每个条目负责 ! 大小的
地址范围;比如需要映射一个大小为 >! 的物理内存,那么就需要填写 > 个条目即可
事实上这就是所谓的段式映射或所谓一级映射,使用 !J 的粗页表,优点是占用条目较少
仅 A5I= 个条目,每个条目 A 字节即每个进程包括内核进程自己仅占用 =K 空间,但缺点
是粒度太大了不利于 内存管理,比如某进程或某内核代码如模块申请一些较小的空
间不足 !,却也得分配这么大空间,当申请频繁时,物理内存消耗将很快。这个缺点是
必须要克服的,# 肯定要引入二级页表,但首先要理解这种段式映射或称为一级映
射的页表是怎么样的,理解了一级映射才能理解二级映射,如下:
现在正式看内核进程的页表创建,先分析道理,再对应源码后面有足量的代码注释,
在 # 文件中,有全局变量 ,如下:
3L
3DJD((2M
3NM
3&2(!*)*+*2M
3&2(!*)*+*2M
3DF0!*+*2*&'*O0DM
3*+'()K"+'()K09M
3'*2B0&9*+*2M
3)"!&K&''M
P4
每个进程都有描述自己内存使用情况的结构 ,内核进程也不例外,从这个
文件的目录可见这个变量是不以平台区分的,现在重点看第二个成员 ,这是该进程内
存页表的虚拟地址,值为 N,这是个在 中定义的变量,值设置为
K0D+0'D&!%&99D#5A55535555A555,由前面已知段式内存页表的大小为 =K,所以
内核的内存页表的虚拟地址范围是Q5555A555R5555>555S。
内核的内存页表,在源码中 函数都映射了什么?由前面已知,映射了三方
面内容,分别是:物理内存、中断向量、硬件 *( 寄存器,先看物理内存的情况,这里
设备物理内存为 T=!,BE(1102 为 5,
函数调用顺序是:#$#$,关注函数
,把物理内存的参数填充到 结构体变量 ,并用它调
用函数 ,正式开始:
、首先一个判断#$C3UU#$-2&K*O0,这是为了
防止虚拟地址不是中断表地址并且在用户区5V6/的情况;然后又是一个判断#$33
!290%*)0 ,, #$ 33 !2D(! UU #$ $3 &/0(1102 UU #$ -
%!&''()0+9,这是为了防止内存类型为 *( 型或 D(! 但虚拟地址为低端内存申请区
6/V6/;<=>!J的情况;这些判断暂无需关注;
、3UQ#$S4由前面可知这是获取所映射内存区间所属的域,以
及是否可读、写、可高速缓存等属性,暂无需关注;
6、判断#$$3555555的情况,这个就不要关注了超过 A/ 的情况;
A、判断#$335UU,,UV0)2*(+!&K的情况,意思
是本区间不为段式映射#$335但该区间可以按 ! 对齐,,U
V0)2*(+!&K,记住这是一个原则,能按 1M 对齐的映射空间就按段式映射,不足 1M
的空间才需要二级映射;
T、3H4,一级一级的看这个函数的实现,最后这个函数相当于
#$;$$3.5555A555;$$,这是在找这个虚拟地址
在内核进程的页表中的位置,由前面已知内核进程的页表从虚拟地址 5555A555 开始,到
5555>555 结束,页表大小为 5A555,这个范围标识 5#5HHHH 这 A/ 的范围,现在 的
值 为 55555555 , 那 么 它 在 内 核 进 程 的 页 表 中 的 位 置 可 以 算 出 来 是 5555A555 ;
5A555.6 A35555<555,为什么是 6 A?因为 55555555 在 5#5HHHH 这 A/ 的范围是整
好 6 A 的位置即 A/ 中的最后一个 /, 值为 55555555,它右移 位值为 5=55,
.5555A555;5=5535555<555,貌似很奇怪为什么不是 5555A=55?这是因为
前面有强制类型转换.,而这个结构的定义是两个 ,所以.5555A555;
5=553.5555A555;5=55.>35555<555,至于为什么 要右移 位,以及
为什么有强制类型转换.,一会再说先关注段式映射的情况;
=、3;4, 指的是要映射的虚拟地址的结尾,它的值为 55555555;
55555555T=!355555555;
<、至此,要映射的空间的虚拟地址起始值 为 55555555,虚拟地址结尾值
为 55555555,长度为 55555555,物理地址起始值为 5,映射类型为变量 的值暂
不关心细节,接下来的 N 循环是真正映射了:
>、L
3M4
WMMMM4
;3#4
34
PN;;MC34
第一行的意思是,只要不超过 ,就获得下一个 !J 的虚拟起始地址,所以传给
W 的 参数,要么与 相差一整段!J,要么是 则不足一整段
!J,我们这里的内存 T=!,不存在 与 相差不足 ! 的情况;
进入函数 W,它的参数分别是“一级页表段页表地址 、虚拟起始地
址 、虚拟结尾地址 现在就是 ;!J、物理起始地址 、内存类型 @;
I、.3HM4,这个 结构就只是一个 大小了,
这里函数 H 的实现就是 3.,地址不变,但类型转变,意思很明
显;
5、判断,,UV0)2*(+!&K335,我们这里的都是 ! 对齐的,
必然 ! 也对齐,底下的U0)2*(+*O0对于我们这里不会成立,我们这里都是 !
对齐,即 值的第 位一直都会是偶数;
、下面的内容是配置段式页表的值和写页表:
L
.3,#$4
;30)2*(+*O04
PN;;M;30)2*(+*O0MC34
X4
第一行,页表的这个条目 ,写入的值是什么,可见,把物理地址和 的映射方
式写进去了4
第二行,累加 ! 的物理地址值;
第三行,只要虚拟地址起始值 再累加 !,没有超过 这里是 ;!,那么
写下一个页表条目;的值,很明显,我们这里会再循环一次,即 里的内容总共运
行过两次;
第四行,最终写入 !!",这个 指向 。
先不要管上面为什么这么实现,先看结果,总共 T=! 的物理内存,最后结果是:
页表条目索引 条目所在地址 页表填的内容 对应的虚拟地址
0xf 0xc0008000 0x
…… …… …… ……
0x3fc 0xc00073fc
0x10000000+typ
e
0xd0000000
…… …… …… ……
0xc05 0xc0007014 0x00500000+typ 0xc0500000
e
0xc04 0xc0007010
0x00400000+typ
e
0xc0400000
0xc03 0xc000700c
0x00300000+typ
e
0xc0300000
0xc02 0xc0007008
0x00200000+typ
e
0xc0200000
0xc01 0xc0007004
0x00100000+typ
e
0xc0100000
0xc00 0xc0007000
0x00000000+typ
e
0xc0000000
…… …… …… ……
0x000 0xc0004000 0x00000000
上面就是对物理内存映射后的情况红色部分,第一列是页表的索引,T=! 的物理内
存 的 的 映 射 部 分 在 第 555 到 56 部 分 , 对 应 页 表 本 身 所 在 地 址 从 5555<555 到
5555<6,这部分页表填充的内容是物理内存和映射类型的或运算结果,它们实际上对
应虚拟地址的 55555555 到 55555555。
如果把一个虚拟地址 56AT=< 给 )" 去访问,那么 )" 把它发给 !!",!!" 会
根据已经建立的映射关系发现这个地址对应的是 55 这个段,然后把后面低 5 位的部分
56AT=< 和 55 拼接起来,结果是 556AT=<。
事实上这里还有很多细节,比如 !!" 到底是怎么能够识别是 55 段的细节,这牵
扯到 硬件体系结构内容,如果不是特殊需要可不特别关心,关注到内核这步即可。
上面是物理内存页表创建的结果,但还有个问题没有说,就是 页表在 中的融
合问题,这部分不理解将影响对全局的理解:
要知道, 要实现高效的内存管理,是不可能按 ! 的区间管理的,这样很容易产
生问题,前面说过这个问题,事实上 是以 AK 为一页作为管理单位即粒度,这是怎么
定的呢?在 文件中规定宏 &/0B*12 为 导致宏 &/0*O0
为 A5I= 即 AK;
既然是 AK 为一页,那么按理说 需要描述 A/ 虚拟内存的话,需要多少个这样的 AK
呢?很简单:G5.G3A/,所以是 G5 为 !,即页表的条目个数为 ! 个,每个条
目占用 A 字节,即页表大小为 A!,每个进程包括内核进程都需要一个内存页表,这就大量
消耗物理内存在页表上;
所以这里将引入多级页表的概念, 内核定义的标准是这样的:最高级 pgd 为页目
录表,它找到每个进程 mm-_struct 结构的 pgd 成员,用它定位到下一级 pmd;第二级
为中间页表,它定位到下一级 ;第三级 是页表,它就能定位到哪个页了;最后虚拟
地址的最后 位定位的是该页的偏移量;
为什么搞的这么麻烦?因为 还要适配 =A 位处理器,到那时是真的需要这么麻烦,
因为否则页表占用空间太大了,所以内核必须搞的级数多一些。
那么 呢, 体系结构的 !!" 实际上支持两级页表,一级是刚才描述的段式映
射即一级映射,再就是支持第二级映射,包括 K、AK、=AK 的页实际上使用的是 AK 页,这
里就牵扯到 页表机制和 页表机制融合的问题;这里记住, 的第一级页表条目
数为 A5I= 个,对于 AK 页第二级目录条目个数为 T= 个,一级二级条目都是每个条目 A 字
节;
剩余21页未读,继续阅读
FSak47
- 粉丝: 237
- 资源: 12
上传资源 快速赚钱
- 我的内容管理 收起
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
会员权益专享
最新资源
- zigbee-cluster-library-specification
- JSBSim Reference Manual
- c++校园超市商品信息管理系统课程设计说明书(含源代码) (2).pdf
- 建筑供配电系统相关课件.pptx
- 企业管理规章制度及管理模式.doc
- vb打开摄像头.doc
- 云计算-可信计算中认证协议改进方案.pdf
- [详细完整版]单片机编程4.ppt
- c语言常用算法.pdf
- c++经典程序代码大全.pdf
- 单片机数字时钟资料.doc
- 11项目管理前沿1.0.pptx
- 基于ssm的“魅力”繁峙宣传网站的设计与实现论文.doc
- 智慧交通综合解决方案.pptx
- 建筑防潮设计-PowerPointPresentati.pptx
- SPC统计过程控制程序.pptx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论1