什么是虚拟内存?
虚拟内存就是说,让物理内存扩充成更大的逻辑内存,从而让程序获得更多的可用内存。虚拟内存使用部分加载的技术,让一个进程或者资源的某些页面加载进内存,从而能够加载更多的进程,甚至能加载比内存大的进程,这样看起来好像内存变大了,这部分内存其实包含了磁盘或者硬盘,并且就叫做虚拟内存。
虚拟内存的实现方式有哪些?
虚拟内存中,允许将一个作业分多次调入内存。采用连续分配方式时,会使得一部分内存空间都处于暂时或永久的空间状态,早餐内存资源的严重浪费,也无法从逻辑上扩大内存容量。因此,虚拟内存的需要建立在离散分配的内存管理方式的基础上。
- 请求分页管理存储
- 请求分段管理存储
- 请求段页式管理存储
为什么进程间的转换比较耗时
进程都有自己的虚拟空间,把虚拟地址转换为真实的物理地址需要通过页表转换,但是页表查找是一个很慢的过程,所以这里引进了快表(TLB),由于每个进程都有自己的虚拟地址空间,并且每个经常都有自己的页表, 那么当进程切换后页表也要进行切换,页表切换后TLB就失效了,TLB命中率降低,则会导致虚拟地址转换为物理地址就会变慢,表现的形式就是程序运行变慢。而线程切换则不会导致TLB失效,因为线程无需切换地址空间,所以进程间的切换比线程间的切换慢。
进程切换时如何管理TLB的内容?
如果仅仅时单纯的清空TLB,那么每次程序运行,访问数据和代码页时,都会触发TLB未命中。如果操作系统频繁地切换进程,会增大开销。
解决方法:有的系统在TLB增加了一个地址空间标识符(Address Space Identifier ,ASID),用来标识当前TLB这一列是那个进程。因此有了ACID,TLB可以缓存不同进程的地址空间映射,没有任何冲突。
如果两个进程共享同一个物理页,那么就会A进程映射到具体的物理页,B也会映射到对应的物理页。共享代码页,减少了内存开销。
什么是分页?
将空间分割成固定长度的分片。分页不是将一个进程的地址空间分割成几个长度不同的逻辑段,而是分割成固定大小的单元,称之为页。把物理内存看成是定长槽块的阵列,叫作页帧。每个页帧包含一个虚拟内存页。
为了记录地址空间的每个虚拟页放在物理内存中的位置,操作系统通常为每个进程保存一个数据结构,称为页表。----用作为地址空间的每个虚拟页面保存地址转换。
页表存储在操作系统的虚拟内存中。
为什么页表查询很慢
因为要使用分页,就要将内存地址空间切分成大量固定大小的页,并且需要记录这些单元的地址映射信息。因为这些映射信息一般存储在物理内存中,所以在转换虚拟地址时,分页逻辑上需要一次额外的内存访问(访问页表+真实内存地址)。每次指令获取、显示加载或保存,都需要额外读一次内存得到转换信息。
以简单的指令
movl 21 ,%eax为例
要获取所需数据,系统必须首先将虚拟地址(21)转换为正确的物理地址(XXX).因此,在从地址(XXX)获取数据之前,系统必须首先从进程的页表中提取适当的页表项,执行转换,然后从物理内存中加载数据。
页面替换算法
最优策略:替换内存中在最远将来才会被访问到的页,可以达到缓存为命中率最低。(可惜没办法知道未来的事情)
FIFO(先进先出):当发生替换时,队列尾部(先进入)的页被提出。
随机:在内存满的时候它随机选择一个页进行替换。
LFU(Least-Frequently-Used): 替换最不经常使用的页(需要依托硬件TLB实现)
LRU(Least-Recently-Used):替换最近最少使用的页
时钟算法(实际使用): 时钟指针开始时指向某个特定的页,当必须进行页替换时,操作系统检查当前指向的页P的使用位是1还是0。如果是1,则意味着页面P最近被使用,因此不适合被替换。然后,把P的使用位设置为0,时钟指针指向下一页。一直持续到找到了一个使用位为0的页,使用位为0意味着这个页最近没有被使用过。如果所有的页都已经被使用了,那么就将所以页的使用位都设置为0,并删除最开始那一页。