物理内存与虚拟内存
所谓物理内存就是我们通常所说的RAM(随机存储器)。在计算机中,还有一个存储
单元叫寄存器,它用于存储计算单元执行指令(如浮点、整数等运算时)的中间结果。寄
存器的大小决定了一次计算可使用的最大数值。
连接处理器和RAM 或者处理器和寄存器的是地址总线,这个地址总线的宽度影响了
物理地址的索引范围,因为总线的宽度决定了处理器一次可以从寄存器或者内存中获取多
少个bit。同时也决定了处理器最大可以寻址的地址空间,如32 位地址总线可以寻址的范
围为0x0000 0000~0xffff ffff。这个范围是232=4 294 967 296 个内存位置,每个地址会引用
一个字节,所以32 位总线宽度可以有4GB 的内存空间。
通常情况下,地址总线和寄存器或者RAM 有相同的位数,因为这样更容易传输数据,
但是也有不一致的情况,如x86 的32 位寄存器宽度的物理地址可能有两种大小,分别是
32 位物理地址和36 位物理地址,拥有36 位物理地址的是Pentium Pro 和更高型号。
除了在学校的编译原理的实践课或者要开发硬件程序的驱动程序时需要直接通过程
序访问存储器外,我们大部分情况下都调用操作系统提供的接口来访问内存,在Java 中
甚至不需要写和内存相关的代码。
不管是在 Windows 系统还是Linux 系统下,我们要运行程序,都要向操作系统先申请
内存地址。通常操作系统管理内存的申请空间是按照进程来管理的,每个进程拥有一段独
立的地址空间,每个进程之间不会相互重合,操作系统也会保证每个进程只能访问自己的
内存空间。这主要是从程序的安全性来考虑的,也便于操作系统来管理物理内存。
其实上面所说的进程的内存空间的独立主要是指逻辑上独立,也就是这个独立是由操
作系统来保证的,但是真正的物理空间是不是只能由一个进程来使用就不一定了。因为随
着程序越来越庞大和设计的多任务性,物理内存无法满足程序的需求,在这种情况下就有
了虚拟内存的出现。
虚拟内存的出现使得多个进程在同时运行时可以共享物理内存,这里的共享只是空间
上共享,在逻辑上它们仍然是不能相互访问的。虚拟地址不但可以让进程共享物理内存、
提高内存利用率,而且还能够扩展内存的地址空间,如一个虚拟地址可能被映射到一段物
理内存、文件或者其他可以寻址的存储上。一个进程在不活动的情况下,操作系统将这个
物理内存中的数据移到一个磁盘文件中(也就是通常Windows 系统上的页面文件,或者
Linux 系统上的交换分区),而真正高效的物理内存留给正在活动的程序使用。在这种情况
下,在我们重新唤醒一个很长时间没有使用的程序时,磁盘会吱吱作响,并且会有一个短
暂的停顿得到印证,这时操作系统又会把磁盘上的数据重新交互到物理内存中。但是我们
必须要避免这种情况的经常出现,如果操作系统频繁地交互物理内存的数据和磁盘数据,
则效率将会非常低,尤其是在Linux 服务器上,我们要关注Linux 中swap 的分区的活跃
度。如果swap 分区被频繁使用,系统将会非常缓慢,很可能意味着物理内存已经严重不
足或者某些程序没有及时释放内存