分页寻址
本文最后更新于 2024年6月7日 下午
文章借鉴 内存寻址之分页机制 与 内存分页、寻址方式那些事
写在前面
分页与分段机制
分段机制是Intel CPU一直保持的机制,而分页机制在80x86的计算机中是一种可选的机制,但只有在保护模式下才存在这种机制,也就是说保护模式下才存在分页寻址的机制,但保护模式不一定开启分页寻址机制.
内存碎片化问题:
- 进程A进来,向os申请了200的内存空间,于是os把0~199分配给A
- 进程B进来,向os申请了5的内存空间,os把200~204分配给它
- 进程C进来,向os申请了100的内存空间,os把205~304分配给它
- 这个时候进程B运行完了,把200-204还给os但是很长时间以后,只要系统中的出现的进程的大小>5的话,200-204这段空间都不会被分配出去(只要A和C不退出)。过了一段更长的时间,内存中就会出现许许多多200-204这样不能被利用的碎片
分页的原因
- 解决内存碎片化问题,分页机制将虚拟内存空间和物理内存空间划分为同样大小的单位-页面,并以页面作为最小分配单位,然后将内存按照页为单位进行内存分配,这样一段内存空间就可以属于很多进程.内存在虚拟中为连续的,物理中离散的.
- 解决程序大小受限问题,如果程序的内存分配是连续的,那么在程序运行开始时,就需要将需要的内存一并开辟,但这样多个程序一起运行的时候就需要非常大的内存.应用了分页机制后,只需将当前页面加载至内存中,其余页面保存在磁盘上,即可解决这个问题.
CPU读取内存内容方式
CPU将虚拟地址翻译为物理地址原理
分页机制打开前,会将页表地址加载进CR3寄存器,寄存器中存储着页表的起始地址.虚拟地址在翻译的过程中被拆分为两部分,前半部分31-12位(20位)为目标地址在页表中的页面号,根据页表的起始地址和页面号,可以在页表中找到物理页面号,取其前20位,将其与虚拟地址的后半部分(12位)拼接成32位的物理地址.
为什么使用两级页表?
32 位环境下,4GB 线性空间分成 4KB 一个页,那就是 1M 个页,每个页表项需要 4 个字节来存储,那么整个 4GB 空间的映射就需要4MB的内存来存储管理信息。这只是一个线性地址空间的映射,每个进程都有自己的映射,假设有100个进程在运行,就需要 400MB 的内存来存储管理信息,太浪费了 。
两级页表结构
第一级称为页目录表。线性地址的高10位产生第一级的索引,根据索引选中页表,可以索引2的10次方,共1024个页表.页目录中的每个元素称为页目录项,每个页目录项所占4字节,故一个页目录共为4KB.
第二级称为页表,由线性地址的11-20位索引,页表中的每一项称为物理页地址,可以索引1024个物理页地址,根据索引从选定的页表中,选取物理页.每个物理页地址为4字节,一个页表为4KB.
通过以上机制,可以索引1024 * 1024 * 4 =4GB的空间.
虚拟地址至物理地址的详细过程
- CR3包含着页目录的起始地址,用32位线性地址的最高10位A31~A22作为页目录的页目录项的索引,将它乘以4,与CR3中的页目录的起始地址相加,形成相应页表的地址。
- 从指定的地址中取出32位页目录项,它的低12位为0,这32位是页表的起始地址。用32位线性地址中的A21~A12位作为页表中的页面的索引,将它乘以4,与页表的起始地址相加,形成32位页面地址。
- 将A11~A0作为相对于页面地址的偏移量,与32位页面地址相加,形成32位物理地址。