**
虚拟内存
**
操作系统中的 CPU 和主内存(Main memory)都是稀缺资源,所有运行在当前操作系统的进程会共享系统中的 CPU 和内存资源,操作系统会使用 CPU 调度器分配 CPU 时间并引入虚拟内存系统以管理物理内存。虚拟内存就是物理内存的一种映射。每个进程在创建时都会绑定一块虚拟内存,需要访问内存时需要虚拟内存的翻译映射到物理内存。如果操作系统发现访问的数据不再内存中,操作系统将以页的方式将数据加载到内存。
虚拟内存的三个关键作用:缓存,隔离权限,进程独立
1.缓存
可以理解为虚拟内存是磁盘上的一块空间,注意是磁盘。内存的顺序访问只是磁盘的一个量级,但是内存的随机访问是磁盘的100000个量级。所以内存很快但很小,磁盘很大但很“慢”。
如上图所示,对于不频繁的数据,其实存放在了磁盘之中。虚拟内存也映射到了磁盘上。但这对用户是无感知的。当这个数据使用频繁,操作系统会将这个数据从磁盘中移入到主存中。这样的操作让上层会觉得内存很大而且很快。其实大的数磁盘并不快,快的是内存并不大。
2.隔离权限
操作系统中的用户程序不应该修改只读的代码段,也不应该读取或者修改内核中的代码和数据结构或者访问私有的以及其他的进程的内存,如果无法对用户进程的内存访问进行限制,攻击者就可以访问和修改其他进程的内存影响系统的安全。
如果每一个进程都持有独立的虚拟内存空间,那么虚拟内存中页表可以理解成进程和物理页的『连接表』,其中可以存储进程和物理页之间的访问关系,包括读权限、写权限和执行权限:内存管理单元可以决定当前进程是否有权限访问目标的物理内存,这样我们就最终将权限管理的功能全部收敛到虚拟内存系统中,减少了可能出现风险的代码路径。
3.进程独立空间
“错误”的让进程以为自己占据了整个内存。每个进程都以为自己是内存的所有者。
既然每个进程的内存空间都是一致而且固定的,所以链接器在链接可执行文件时,可以设定内存地址,而不用去管这些数据最终实际的内存地址,这是有独立内存空间的好处。当不同的进程使用同样的代码时,比如库文件中的代码,物理内存中可以只存储一份这样的代码,不同的进程只需要把自己的虚拟内存映射过去就可以了,节省内存,在程序需要分配连续的内存空间的时候,只需要在虚拟内存空间分配连续空间,而不需要实际物理内存的连续空间,可以利用碎片。进程之间可以共享物理内存而节约开销。
4.缺页中断、页面替换
某种情况下,用户访问的数据不在内存中。则发生缺页中断。可以认为虚拟空间都被映射到了磁盘空间中,事实上也是按需要映射到磁盘空间上,通过mmap,并且由页表记录映射位置,当访问到某个地址的时候,通过页表中的有效位,可以得知此数据是否在内存中,如果不是,则通过缺页异常,将磁盘对应的数据拷贝到内存中。
主内存是有限的,当主内存满了不足以存放新的内存时,操作系统会选择合适的物理内存驱逐回磁盘之中。给新的内存让位置,这个驱逐过程就叫页面替换。
总结
虚拟内存可以结合磁盘和物理内存的优势为进程提供看起来速度足够快并且容量足够大的存储;
虚拟内存可以为进程提供独立的内存空间并引入多层的页表结构将虚拟内存翻译成物理内存,进程之间可以共享物理内存减少开销,也能简化程序的链接、装载以及内存分配过程;
虚拟内存可以控制进程对物理内存的访问,隔离不同进程的访问权限,提高系统的安全性;