彻底搞懂虚拟内存,虚拟地址,虚拟地址空间( 二 )


【段选择子+段偏移地址】中的段选择子可以认为是一个索引,这个索引指向了全局段描述符表中的一项,全局段描述表存储在内存中,它的起始地址存储在全局段描述符寄存器中 。
全局段描述符表有很多个段描述符,每个段描述占用8个字节,这个段描述符里面就包括了段基址,另外还有一些安全性相关的描述信息例如段的可读,可写,可执行,段的大小等 。
段选择子存储在了段寄存器中,总共16位,其中高13位就是全局段描述表的索引 。
当CPU开始执行代码段的第一条指令时,会将代码段的选择子放入到CS段寄存器中,然后CPU从段寄存器中的获取段选择子,然后截取选择子的高13位获取索引,然后根据全局描述符表寄存器的地址找到全局描述符表的起始地址,根据起始地址+索引*8找到段描述符,然后根据段描述符获取段的基址,段的基址加上ip寄存器中的偏移地址就是指令的物理地址,如下图所示1~6步骤所示

彻底搞懂虚拟内存,虚拟地址,虚拟地址空间

文章插图
定位指令
当CPU执行到0x00600000处的代码指令时,该指令为MOV AX,[0],该指令的意思是把地址0处的数据存储到AX寄存器,这个0就是数据段的偏移地址,此时CPU会将数据段的选择子加入到DS段寄存器中,然后CPU获取段选择的高13位获取索引,然后根据全局描述符表寄存器的地址找到全局描述符表的起始地址,根据起始地址+索引*8找到段描述符,然后根据段描述符获取段的基址,段的基址加上数据段的偏移地址就是数据的物理地址,如下图1~6步骤所示
彻底搞懂虚拟内存,虚拟地址,虚拟地址空间

文章插图
定位数据
上述过程就是【段选择子+段偏移地址】的定位方式 。
虚拟地址现代的操作系统和CPU未打开分页时采用的是【段选择子+段偏移地址】访问代码和数据,而一旦打开分页时,经过【段选择子+段偏移地址】得到的地址不再是物理地址了,而是叫做虚拟地址,默认则是打开分页的 。
现代的操作系统和CPU采用的平坦模型,平坦模型就是整个内存就一个段,因此段基址就是0,段偏移地址就等于虚拟地址了 。
下面将从以下几个方面来阐述虚拟地址相关的话题 。
1.什么是虚拟地址,物理地址,虚拟地址空间,物理地址空间,虚拟内存,物理内存?
2.什么是进程虚拟地址空间?
3.什么是虚拟页,物理页?
4.什么是页表?
5.虚拟地址怎么样访问物理内存?
什么是虚拟地址,物理地址,虚拟地址空间,物理地址空间,虚拟内存,物理内存?虚拟地址空间是虚拟地址的集合,假设虚拟地址空间是N位的,它的地址范围为{0~2的N次方-1}即它有2的N次方个虚拟地址,例如16位的虚拟地址空间,它的地址范围为{0~65535},这意味着16位的虚拟地址空间有65536个虚拟地址 。
物理地址空间是物理地址的集合,假设物理地址空间有M个字节,它的地址范围为{0~M-1},M不一定是2的多少次幂,例如M=100,表示物理地址空间大小为100个字节,它的地址范围为{0~99},通常情况下物理地址空间是2的幂次方,例如65536,这也是为了计算机方便处理而已,并不是强制要求的 。
物理内存可以认为是一个的物理字节数组,每个物理地址指向这个物理字节数组中的一项 。
虚拟内存也一样,它也可以认为是一个物理字节数组,不过这个字节数组是存储在磁盘上 。
物理地址空间是物理内存的范围,虚拟地址空间是虚拟内存的范围,物理地址空间中的每个物理地址都是实打实地指向了具体的存储单元,虚拟地址空间中每个虚拟地址指向哪里有3种情况:
a.未分配,这个虚拟地址仅仅是个数字而已,没有任何指向 。
b.未缓冲,这个虚拟地址指向了磁盘的某个字节存储单元,里面存储了指令或者数据 。
c.已缓冲,这个虚拟地址指向了物理内存的某个字节存储单元,里面存储了指令或者数据 。
2.什么是进程虚拟地址空间?操作系统加载可执行文件后,创建了一个进程,这个进程就有了自己的虚拟地址空间,每个进程的虚拟地址空间都一样,如下图所示
彻底搞懂虚拟内存,虚拟地址,虚拟地址空间

文章插图
进程虚拟地址空间
如上图所示,进程的虚拟地址空间被统一划分成了多个固定区域,例如代码区,数据区,堆区,共享区,栈区,内核区 。
代码区和数据区域:来自于可执行文件,代码区和数据区挨着,代码区总是在0x0040000地址以上,0x0040000地址以下另有它用 。


推荐阅读