深入理解linux内核--内存3
硬件中的分页
为了效率,线性地址被分为固定长度的组,成为”页“,页内连续的线性地址被映射到连续的物理地址。这样,内核可以指定一个页的物理地址和其存取权限。把线性地址映射到物理地址的数据结构被称为”页表“,页表在主存中。
386开始,页为4kb
directory:最高10位,Table(页表):中间10位;Offset:最低12位;
二级模式的目的是为了减少每个进程页表所需的RAM数量。
每个活动的进程必须分配一个页目录,不过没有必要为进程的所有页表都分配RAM。只有在进程实际需要一个页表时才分配RAM。
正在使用的页目录的物理地址存放在cr3寄存器。线性地址中的directory字段只是存在页目录中的目录项。而页目录项指向适当的页表,地址Table字段说明页表中的表项。表项中存放的是页框的物理地址。
页目录项和页表项有相同的结构,有以下字段:
Present标志,包含页框物理地址最高20位的字段,accessed,dirty,read/write...
扩展分页:
允许页框大小是4MB
物理地址扩展(PAE)分页机制:
现在处理器的寻址数目由32增加到36.RAM大小为64GB,页表项物理地址字段由20位扩展到24位。页表项大小由32位变成64位。如果页目录项中的页大小标志PS启用大尺寸页(在PAE启用时为2MB)
结果4KB页表包含512个页表项而不是1024个表项。
引入一个叫页目录指针表的页表新级别,它由4个64位表项组成。
cr3包含一个27位的页目录指针表(PDPT)基地址字段。
当把线性地址映射到4KB的页时,32位线性地址按下列方式解释:
cr3:指向一个PDPT;
31-30:指向PDPT中4个项中的一个;
29-21:指向页目录项中512个项中的一个;
20-12:指向页表中512项中的一个;
位11-0:4KB页中的偏移量;
总之,一旦CR3被设置,就可寻址高达4GBRAM。如果希望对更多的RAM寻址,就必须在CR3中方一个新值。
但是线性地址仍然是32位,也就意味着同一个线性地址映射不同的RAM区。很明显,PAE并没有扩大进程的线性地址空间,因为它只能处理物理地址。此外,只有内核能够修改进程的页表,所以用户态下运行的进程不能使用大于4GB的物理地址空间。但是,内核的使用容量高达64GBRAM,从而显著增加了系统中的进程数量。
高速缓存
linux清楚了所有页目录项和页表项中的PCD和PWT,对所有页框都启用高速缓存,对于写操作,总是回写策略。
Linux中的分页
linux的分页模型同时适用32位和64位系统。linux从2.6.11开始,采用四级分页模型。
- 页全局目录
- 页上级目录
- 页中间目录
- 页表
线性地址因此被分为5个部分。如果是32位系统没有启用物理扩展的情况下,让”页上级目录“和”页中间目录“位全为0,从而恢复2级目录。
- 给每个进程分配一块不同的物理地址空间,确保了寻址错误;
- 区别页和页框;
- 每个进程有它自己的页全局目录和自己的页表集。
物理内存布局
一般来说linux内核安装在物理地址0x00100000开始的地方,也就是在第2个MB开始。
进程页表
0x0000 0000-0xbfff ffff的线性地址,无论进程运行在用户态还是内核态都可以寻址。
0xc000 0000-0xffff ffff的线性地址,只有内核态的进程才能寻址。
内核页表
内核线性地址是1GB,1GB= 12MB特殊映射+896MB
linux映射一个896MB的RAM窗口到内核的线性地址空间。剩余的RAM留着不映射,并由动态重映射。而且着896MB的线性地址是映射到物理内存低位区域。而且这896MB的线性地址所建立的映射是线性的,映射的物理地址=线性地址=PAGE_OFFSET
所以至少128MB的内核线性地址留作它用,可以是非连续内存分配和固定映射地址。
固定映射的线性地址类似常量映射,它和物理地址不是线性的,但是固定不变的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)