分页机制是如何建立起来的?地址如何转换?
1、逻辑地址,线性地址,虚拟地址,物理地址傻傻分不清?
(1)逻辑地址
在IA-32架构下,分段是必须的,而分页并不是必须的。不论分页与否,访问内存都必须采用“段基址:段内偏移地址”的策略。 因此访问内存需要16&32共48位的地址信息,这便是逻辑地址,高12位为段选择子,后面32位为段内偏移地址。
(2)线性地址
使用选择子索引到段描述符取得32位的段基址后与逻辑地址内的32位段内偏移地址相加后得到一个32位的地址信息,这便是线性地址。
(3)虚拟地址
如果不启用分页机制,线性地址就是物理地址,而如果启用分页机制的话,线性地址又叫做虚拟地址。
(4)物理地址
物理地址,不用多说,内存单元的真正地址
2、什么是分页?
分页本质上是将各种大小不同的内存段拆分成大小相同的内存块(通常4KB),以便进行内存管理的一种机制。
3、为什么要分页?
主要是便于内存管理,解决纯分段情况下应用程序过多,或者内存碎片过多而无法容纳新进程。又或者重新加载某内存段(之前交换出去的)时找不到合适的内存区域的问题。 造成这情况的原因:只分段的情况下,线性地址就是物理地址,两者都是连续的,不够灵活,不可能每次都能找到合适的内存区域。而分页的话,线性地址需要进一步转化为物理地址,线性地址是连续的,但是物理地址可以不连续,这样的话寻找合适的内存区域时就很灵活,解决了上述问题。
4、分页机制?(基于32位系统)
(1)页表
分页机制的核心功能是实现虚拟地址到物理地址的转化,如何转化呢?靠的是页表将虚拟地址和物理地址建立起映射关系,有了这映射关系,便可将虚拟地址转化成实际的物理地址。 总的思想是:将虚拟地址的高20位视作索引号,在页表中进行索引页表项,得到物理基址,将其与虚拟地址的低12位偏移地址相加后便得到最后的物理地址。 这也是一级页表下虚拟地址转化为物理地址的方式,然而一级页表并不适用,一般会使用多级页表。
(2)页目录项,页表项
页目录项和页表项的结构以及属性位简介如下:
(3)二级页表及地址转换
二级页表下虚拟地址到物理地址转化的原理与一级页表下转化的原理相同,只是多进行了一步转化。具体流程先看图: 第一步:使用段选择子去GDT中索引段描述符,“取出”段基址,段部件将段基址与偏移地址相加得到线性地址,也即虚拟地址。 第二步:将虚拟地址的高10位作为索引号,索引页目录表中的页目录项,具体操作:将虚拟地址高10位乘4加上CR3中的页目录物理地址,得到所要的页目录项的地址,即a+0x44。 第三步:将虚拟地址的中10位作为索引号索引二级页表中的页表项,具体操作:“取出”页目录项中的20位页表物理地址,即0x1000。再加上虚拟地址中10位乘4,得到物理页地址,即0x1000+0x2344。 第四步:虚拟地址的后12位偏移地址和第三步得到的物理页地址相加得到最后实际的物理地址。如图中所示:0xfa000+0x567=0xfa567为最后target的物理地址。
以上就是二级页表下地址转化的过程,三级乃至多级页表下地址转化的方法都一样,不过是多重复了第三步的操作。
注:分页机制的作用是将虚拟地址转化为物理地址,但在实际转化的过程中相当于在关闭分页机制条件下进行的。即地址转化的过程中涉及的地址(CR3中页目录地址,页目录项地址,页表项地址)都是实际的物理地址,不会被分页机制继续转化,否则的话会无限递归下去。
(4)为什么一级页表不适用?
1个4B大小的页表项指向4K的页面,映射整个4G空间的话需要4G / 4K = 1M 个页表项,因此整个页表大小为4M。 一个进程便需要4M大小的页表,如果说有很多进程则会花费许多内存来储存页表。再者这还只是32位的系统,内存空间只有2^32^B = 4GB,若是64位系统,则需要 2^64^ / 2^12^ = 252个页表项 ,那简直不可想象。
(5)多级页表为什么比一级页表省空间?
首先页表就是一个整体,一级页表下4M(32位)的页表就是一个整体,需要全部创建,所以每个进程都要有4M的页表,这样的话页表所占用的空间的确很多。 而多级页表只会为进程实际使用的那部分虚拟内存建立页表,只用一级页表需要建立所有的页表项,而多级页表只建立了需要的页表,如此当然更省空间。 那为什么多级页表下就只需要建立需要的那部分页表呢? 多级页表相当于对一级页表再次进行分页,将一张大页表拆成了多张小页表,以后想用几张便做几张,这样就很灵活而且省空间。 一些操作系统虚拟内存管理系统也是这么实现的,只有某个虚拟地址需要一张新页表来映射时,才会为它分配物理页,这就做到了需要才建立的原则,因而比一级页表更省空间。
5、如何建立分页机制?(大致思路)
1、建立初始页表,建立页表就是建立映射关系,建立映射关系就是添加页表项。操作系统内核的虚拟地址在0xc0000000以上,而最开始我们工作的地址是在物理内存的低端1M,所以这里的映射关系为将物理内存的低端1M映射到虚拟地址空间的0xc0000000以上。 2、GDT,内核栈等等都应放在内核中,需要修改其地址值,还有一些描述符中的段基址也需要修改,因为原来的地址是实际的物理地址,启用分页后应采用虚拟地址。 3、把页目录地址赋给CR3寄存器。 4、将CR0寄存器的PE位置1,开启分页机制。 5、重新加载GDT。
至此便启用了分页机制,随后系统运行中出现的地址都是虚拟地址,需要经过上述图中所示的转化来获得实际的物理地址。
5、分页的缺点?如何解决?
分页虽然很灵活,但是需要做多次计算,多次访问内存。每一个虚拟地址都要重复上述操作的话,处理器的负担过重,时间也花费过多。 如何解决呢? 利用局部性原理为地址转换建立了一个高速缓存,TLB,俗称快表。 有了TLB,处理器在寻址之前会先利用虚拟地址的高20位在TLB中查找相应条目,如果命中,则返回虚拟地址所映射的物理页地址,否则便去查询页表,找到相应物理页地址后再更新TLB。
原创不易,喜欢本文的朋友还请点赞支持一下再走呀!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java 中 RMI 的使用
RMI 介绍 RMI (Remote Method Invocation) 模型是一种分布式对象应用,使用 RMI 技术可以使一个 JVM 中的对象,调用另一个 JVM 中的对象方法并获取调用结果。这里的另一个 JVM 可以在同一台计算机也可以是远程计算机。因此,RMI 意味着需要一个 Server 端和一个 Client 端。 Server 端通常会创建一个对象,并使之可以被远程访问。 这个对象被称为远程对象。 Server 端需要注册这个对象可以被 Client 远程访问。 Client 端调用可以被远程访问的对象上的方法,Client 端就可以和 Server 端进行通信并相互传递信息。 说到这里,是不是发现使用 RMI 在构建一个分布式应用时十分方便,它和 RPC 一样可以实现分布式应用之间的互相通信,甚至和现在的微服务思想都十分类似。 RMI 工作原理 正所谓 “知其然知其所以然”,在开始编写 RMI 代码之前,有必要了解一下 RMI 的工作原理,RMI 中 Client 端是和 Server 端是如何通信的呢? 下图的可以帮助我们理解RMI 的工作流程。 从图中可以看到,C...
- 下一篇
Linux内核中断之中断初始化
本文基于RockPI 4A单板Linux4.4内核介绍中断初始化流程。 一、内核中断初始化 文件:kernel\init\main.c。 Linux内核中断初始化流程如下: start_kernel()-> init_IRQ()-> irqchip_init()-> of_irq_init(__irqchip_of_table) ## 扫描和初始化设备树中的中断控制器("interrupt-controller") __irqchip_of_table在RK3399中断控制器GICv3初始化时赋值。 二、中断控制器初始化 文件:drivers/irqchip/irq-gic-v3.c。 中断控制器GICv3初始化流程如下: IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init); gic_of_init()-> gic_init_bases()-> set_handle_irq(gic_handle_irq) ## 设置handle_arch_irq = gic_handle_irq,中断触发...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池