| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> 06-虚幻与真实:程序中的地址如何转换? -> 正文阅读 |
|
[游戏开发]06-虚幻与真实:程序中的地址如何转换? |
????????假设在内存中放入A、B两个程序,怎么保证两段程序没有内存地址的冲突?怎么保证两段程序不会互相读写各自的内存空间?怎么解决内存容量问题?(程序在不断开发迭代中程序代码占用的空间越来越大,内存不够)怎么解决扩展后的复杂情况?(如果有程序C、D、E……) ????????一个较好的方案是:让所有的程序都各自享有一个从0开始到最大地址的空间,这个地址空间是独立的,是该程序私有的,其它程序既看不到,也不能访问该地址空间,这个地址空间和其它程序无关,和具体的计算机也无关。 这个方案就是虚拟地址。 虚拟地址将Hello World二进制文件反汇编后得到的代码
上述代码中,左边第一列数据就是虚拟地址,第三列中是程序指令,如:“mov 0x200af5(%rip),%rax,je 4fa,callq *%rax”指令中的数据都是虚拟地址。 事实上,所有的应用程序开始的部分都是这样的。这正是因为每个应用程序的虚拟地址空间都是相同且独立的。 而这个地址是链接器产生的。其实我们开发软件经过编译步骤后,就需要链接成可执行文件才可以运行,而链接器的主要工作就是把多个代码模块组装在一起,并解决模块之间的引用,即处理程序代码间的地址引用,形成程序运行的静态内存空间视图。 虚拟地址到物理地址的转换相当于一个函数:p=f(v),输入虚拟地址v,输出物理地址p。 实现:MMU(内存管理单元) ?把虚拟地址空间和物理地址空间都分成同等大小的块,也称为页,按照虚拟页和物理页进行转换。根据软件配置不同,这个页的大小可以设置为4KB、2MB、4MB、1GB,这样就进入了现代内存管理模式——分页模型。 一个虚拟页可以对应到一个物理页,由于页大小一经配置就是固定的,所以在地址关系转换表中,只要存放虚拟页地址对应的物理页地址就行了。 MMU页表地址转换关系表,即页表。 为了增加灵活性和节约物理内存空间(因为页表是放在物理内存中的),所以页表中并不存放虚拟地址和物理地址的对应关系,只存放物理页面的地址,MMU以虚拟地址为索引去查表返回物理页面地址,而且页表是分级的,总体分为三个部分:一个顶级页目录,多个中级页目录,最后才是页表。 ?保护模式下的分页保护模式的内存模型是分段模型,它并不适合于MMU的分页模型,所以我们要使用保护模式的平坦模式,这样就绕过了分段模型。这个平坦模型和长模式下忽略段基址和段长度是异曲同工的。地址产生的过程如下所示。 ????????程序代码中的虚拟地址,经过CPU的分段机制产生了线性地址,平坦模式和长模式下线性地址和虚拟地址是相等的。 如果不开启MMU,在保护模式下可以关闭MMU,这个线性地址就是物理地址。因为长模式下的分段弱化了地址空间的隔离,所以开启MMU是必须要做的,开启MMU才能内存地址空间保存。 根据前面得知32位虚拟地址经过分段机制之后得到线性地址,又因为通常使用平坦模式,所以线性地址和虚拟地址是相同的。 保护模式下的分页大小通常有两种,一种是4KB大小的页,一种是4MB大小的页。分页大小的不同,会导致虚拟地址位段的分隔和页目录的层级不同,但虚拟页和物理页的大小始终是等同的。 ?保护模式下的分页——4KB页该分页方式下,32位虚拟地址被分为三个位段:页目录索引、页表索引、页内偏移,只有一级页目录,其中包含1024个条目 ,每个条目指向一个页表,每个页表中有1024个条目。其中一个条目就指向一个物理页,每个物理页4KB。这正好是4GB地址空间。如下图所示。 上图中CR3就是CPU的一个32位的寄存器,MMU就是根据这个寄存器找到页目录的。下面,我们看看当前分页模式下的CR3、页目录项、页表项的格式。 ?可以看到,页目录项、页表项都是4字节32位,1024个项正好是4KB(一个页),因此它们的地址始终是4KB对齐的,所以低12位才可以另作它用,形成了页面的相关属性,如是否存在、是否可读可写、是用户页还是内核页、是否已写入、是否已访问等。 ?保护模式下的分页——4MB页该分页方式下,32位虚拟地址被分为两个位段:页表索引、页内偏移,只有一级页目录,其中包含1024个条目。其中一个条目指向一个物理页,每个物理页4MB,正好为4GB地址空间,如下图所示。 CR3还是32位的寄存器,只不过不再指向顶级页目录了,而是指向一个4KB大小的页表,这个页表依然要4KB地址对齐,其中包含1024个页表项,格式如下图。 可以发现,4MB大小的页面下,页表项还是4字节32位,但只需要用高10位来保存物理页面的基地址就可以。因为每个物理页面都是4MB,所以低22位始终为0,为了兼容4MB页表项低8位和4KB页表项一样,只不过第7位变成了PS位,且必须为1,而PAT位移到了12位。 长模式下的分页如果开启了长模式,则必须同时开启分页模式,因为长模式弱化了分段模型,而分段模型也确实有很多不足,不适应现在操作系统和应用软件的发展。 同时,长模式也扩展了CPU的位宽,使得CPU能使用64位的超大内存地址空间。所以,长模式下的虚拟地址必须等于线性地址且为64位。 长模式下的分页大小通常也有两种,4KB大小的页和2MB大小的页。 长模式下的分页——4KB页该分页方式下,64位虚拟地址被分为6个位段,分别是:保留位段,顶级页目录索引、页目录指针索引、页目录索引、页表索引、页内偏移,顶级页目录、页目录指针、页目录、页表各占有4KB大小,其中各有512个条目,每个条目8字节64位大小,如下图所示。 上面图中CR3已经变成64位的CPU的寄存器,它指向一个顶级页目录,里面的顶级页目项指向页目录指针,依次类推。 需要注意的是,虚拟地址48到63这6位是根据第47位来决定的,47位为1,它们就为1,反之为0,这是因为x86 CPU并没有实现全64位的地址总线,而是只实现了48位,但是CPU的寄存器却是64位的。 这种最高有效位填充的方式,即使后面扩展CPU的地址总线也不会有任何影响,下面我们去看看当前分页模式下的CR3、顶级页目录项、页目录指针项、页目录项、页表项的格式,我画了一张图帮你理解。 长模式下的分页——2MB页在这种分页方式下,64位虚拟地址被分为5个位段 :保留位段、顶级页目录索引、页目录指针索引、页目录索引,页内偏移,顶级页目录、页目录指针、页目录各占有4KB大小,其中各有512个条目,每个条目8字节64位大小。 可以发现,长模式下2MB和4KB分页的区别是,2MB分页下是页目录项直接指向了2MB大小的物理页面,放弃了页表项,然后把虚拟地址的低21位作为页内偏移,21位正好索引2MB大小的地址空间。 下面我们还是要去看看2MB分页模式下的CR3、顶级页目录项、页目录指针项、页目录项的格式,格式如下图。 上图中没有了页表项,取而代之的是,页目录项中直接存放了2MB物理页基地址。由于物理页始终2MB对齐,所以其地址的低21位为0,用于存放页面属性位。 开启MMU要使用分页模式就必先开启MMU,但是开启MMU的前提是CPU进入保护模式或者长模式,开启CPU这两种模式的方法,我们在前面第五节课已经讲过了,下面我们就来开启MMU,步骤如下: 1.使CPU进入保护模式或者长模式。 2.准备好页表数据,这包含顶级页目录,中间层页目录,页表,假定我们已经编写了代码,在物理内存中生成了这些数据。 3.把顶级页目录的物理内存地址赋值给CR3寄存器。
MMU地址转换失败MMU的主要功能是根据页表数据把虚拟地址转换成物理地址,但有没有可能转换失败? 绝对有可能,例如,页表项中的数据为空,用户程序访问了超级管理者的页面,向只读页面中写入数据。这些都会导致MMU地址转换失败。 MMU地址转换失败了怎么办呢?失败了既不能放行,也不是reset,MMU执行的操作如下。 1.MMU停止转换地址。 这里你只要先明白这个流程就好了,后面课程讲到内存管理的时候我们继续探讨。 重点回顾首先,我们从一个场景开始热身,发现多道程序同时运行有很多问题,都是内存相关的问题,内存需要隔离和保护。从而提出了虚拟地址与物理地址分离,让应用程序从实际的物理内存中解耦出来。 虽然虚拟地址是个非常不错的方案,但是虚拟地址必须转换成物理地址,才能在硬件上执行。为了执行这个转换过程,才开发出了MMU(内存管理单元),MMU增加了转换的灵活性,它的实现方式是硬件执行转换过程,但又依赖于软件提供的地址转换表。 最后,我们下落到具体的硬件平台,研究了x86 CPU上的MMU。 x86 CPU上的MMU在其保护模式和长模式下提供4KB、2MB、4MB等页面转换方案,我们详细分析了它们的页表格式。同时,也搞清楚了如何开启MMU,以及MMU地址转换失败后执行的操作。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/28 3:32:05- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |