面试被问到虚拟内存,回答的感觉不够。于是重新总结一下。

程序猿对内存的要求都是:私有的、速度快、容量无限大。

对应现在的现况:使用一块物理内存、容量有限、并且速度有限,需要cpu多级缓存。

物理内存暴露给进程存在问题:1.如果可以寻址内存的每个字节,容易破坏操作系统以及其他进程

解决方法1

通过基址寄存器与界限寄存器

前置保存起始物理地址,后者保存地址长度;解决了地址私有化的问题。

交换技术  仍然使用两个寄存器,会产生内存空洞;就算使用内存紧缩技术(移动进程空间),也会大量占用cpu时间;

虚拟内存:

核心思想:每个进程拥有拥有独立的虚拟地址空间,被分割成多个页块,被映射到物理内存,但并不是所有页都在内存中才能够运行程序;如果程序引用到了一段内存地址空间时,如堆内存中的一个变量,虚拟地址不是直接送到地址总线上,而是送到mmu,由硬件执行必要的映射,将变换后将变换的地址送到总线上;如果mmu判断请求的数据不再ram中,则产生缺页中断,使cpu陷入内核,将缺失的页面装入物理内存,修改mmu映射关系并重新执行失败的指令。

如果mmu没有启动,cpu发出的内存地址将直接传到总线上,被物理内存芯片接受。

所以说mmu对于程序来说是透明的  也不需要陷入内核态才能工作,由硬件直接完成。

所以说虚拟内存的本质就是创造一个新的抽象概念-地址空间,对物理内存进行抽象;类似于进程是对cpu的抽象;实现就是将虚拟地址空间分解成页。并将每一页映射到物理内存的页框中或者暂时接触映射。

以下图片可以说明:


 linux内存管理-虚拟内存总结_第1张图片

所以说,对于linux而言,这些交换出去的页面就会在磁盘上,而对于linux,用户交换的磁盘空间必须是一个独立的分区,这个分区就是swap分区,swap分区也是文件系统,需要用fdisk调整分区类型为82,mkswap命令创建交换分区才能使用,一般是打开的文件可以交换出去,而代码段以及变量是不能交换出去的,这个交换的过程叫做pageout、pagein  对应swap而言,就叫做swap in  swap out。linux以交换分析的形式允许内存的过载使用。因为磁盘的IO性能和内存不在一个数量级上,使用磁盘作为swap分区必然会导致系统性能的降低,然而,不允许过载使用的话对于linux是非常危险的,一旦内存满了之后,对于操作系统而言也无法用空闲的内存页面完成必须的工作,就会杀死一些进程导致服务的不可用。

 

使用free命令

wKiom1b2myvjCN-uAAAZrYKfrQA960.png





中还有两个重要的参数:buffers,以及cached

缓存(cached)是把读取过的数据保存起来,重新读取时若命中(找到需要的数据)就不

要去读硬盘了,若没有命中就读硬盘。其中的数据会根据读取频率进行组织,把最频繁读

取的内容放在最容易找到的位置,把不再读的内容不断往后排,直至从中删除。

缓冲(buffers)是根据磁盘的读写设计的,把分散的写操作集中进行,减少磁盘碎片和硬盘的反复寻道,从而提高系统性能。linux有一个守护进程定期清空缓冲内容(即写如磁盘),也可以通过sync命令手动清空缓冲。举个例子吧:我这里有一个ext2的U盘,我往里面cp一个3M的MP3,但U盘的灯没有跳动,过了一会儿(或者手动输入sync)U盘的灯就跳动起来了。卸载设备时会清空缓冲,所以有些时候卸载一个设备时要等上几秒钟。所以说将buffer和cached加上之后,free就增多了,如

 

所以说呢,缓存 cache是匹配生产者比消费者慢的情况儿缓冲buffer是匹配生产者比消费者快的情况。

同时,虚拟内存也会涉及到另一个概念,使用top命令

linux内存管理-虚拟内存总结_第2张图片

Virtres就对应到上面所讲的虚拟内存了。

VIRTvirtual memory usage 

进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据等

假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m,而不是实际的使用量。

RES:resident memory usage 常驻内存值得就是实际占用的物理页面了。 

当时这里有个问题,按理来说,virt=res+swap,可是这里明显不是virt有4个g,而swap为0,res为400m,显然不对,这个问题还需要进一步研究。