Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

背景

最近在深入学习操作系统,以32位的Linux操作系统为例,使用Bochs这个x86模拟器时,创建了32MB的物理内存,因为地址总线是32位,所以能访问4GB的内存空间。为什么不创建一个32GB的物理内存呢?这样在做地址映射的时候就能让虚拟地址和物理地址一一对应了。为什么虚拟地址空间要比物理地址空间大呢?这样不会导致多个相同的虚拟地址映射到同一个物理地址上吗?通过查阅多种资料,终于揭开了虚拟地址奥秘!

提出问题

1.虚拟地址空间有多大?

2.虚拟地址是如何和物理地址建立映射关系的?

3.虚拟地址是如何做到地址隔离的?

为什么需要虚拟地址

8086之前 —> 8086—> 80286—>80386—>IA32

​ 计算机的发展是一个不断向上兼容的过程,在8086计算机之前,运行程序使用的都是实际的物理地址,用户指哪打哪,但是这种计算机运行效率是十分低下的,即使内存足够多个进程同时运行,只要有两个进程的编址发生冲突,那么就无法运行。

​ 为了解决编址冲突的问题,提出程序重定位,“分段访问”机制由此而来,这就是著名的8086计算机,但是尽管8086计算机使用了重定位解决了地址冲突问题,但是地址仍然是物理地址,地址总线是20位,只能访问1MB内存空间;寄存器是16位的,当使用寄存器访存的时候,还需要对其进行右移4位才能访问到1MB地址空间。

​ 8086计算机

虚拟地址到底有多大

​ 以32位的Linux操作系统为例,虚拟地址空间和物理地址空间都不会超过4GB,这是因为地址总线只有32位,CPU能访问到的最大地址空间是0xffffffff,当超过32GB时,地址总线也无法访问到了,所以超过地址总线能访问到的最大的物理内存是没有意义的。

​ 物理地址空间可以小于4GB,因为我们还有硬盘这个大存储,当内存不够用时可以将不常用的内存换出到硬盘中。但是虚拟地址空间大小是地址总线能够访问到的最大地址,也就是4GB。

虚拟地址如何和物理地址建立映射

​ 在前面一个博文中我说到,操作系统中存在两个全局变量,分别是内核物理内存池和用户物理内存池,使用bitmap一串二进制格式的数据结构跟踪物理页的分配情况,物理内存池中的地址均是实际的物理地址,它是不需要通过地址转换直接送上地址总线去访存的。

​ 操作系统为每一个进程都分配了一个虚拟地址池,包括操作系统进程和用户进程。所以虚拟地址池不是全局变量了,它是每个进程的私有数据结构。

评论