虚拟内存的作用
直译是虚拟内存,对于WINDOWS下的用户,直观的感受是,在硬盘上开辟一片区域当内存用。而LINUX下的用户,直观感受是,一个进程的内存占用,分虚拟内存与物理内存。
虚拟内存的作用,个人理解,主要有几个:
(1)简化开发,每个进程都可以认为自己占有整个内存,这对多任务系统很重要,早期有些系统,甚至需要使用相对地址,再根据代码载入内存的基准地址,算出真正要访问哪个内存地址
(2)利用多级存储系统,把硬盘或别的存储介质当内存使用,在内存不足的系统,这点很重要,线上服务的机器,为了确保响应速度,一般会关闭这个功能
(3)节省内存,用户往往事先不知道需要用多少内存,所以会申请一个很大的数组,会造成浪费,所以刚开始的时候,是只分配虚拟内存,当用到的时候才分配物理内存
对于第二点,对于多级存储系统,其实一般就两级,内存跟硬盘,还需要有一个淘汰策略决定什么内存放哪。如果有三种存储介质,比如SSD,LINUX在这种情况下会出错。如果内存不够,而硬盘上开了SWAP分区(也就是虚拟内存了),LINUX的行为是,先把数据读到SWAP,然后再从SWAP读数据,SSD白搭了。
具体实现的时候,是把内存分页,一个页面一般是4K,当访问一个还没分配出来的内存单元的时候,会把该内存单元所在的整个页面都分配出来。这样一个好处是,逻辑上连续的虚拟地址,可以映射成不连续的物理地址。
MMAP实现的时候,就是以页为单位分配内存。以前出过一次CORE,是用MMAP读文本文件,用了很多字符串函数,默认输入数据是以'\0'结束的。问题是文本文件里是不可能有'\0'的,这个'\0'其实是mmap读入数据的时候,对一个内存页里空的数据都置0。运气不好的时候,文件大小正好是4K的整数次倍,后面就没有'\0',就一直往后读,最后CORE了
不是所有的内存都分页的,有部分内存是被OS强制占用,以确保性能。
还有一种实现方式是把内存分段,不过已经不常用了。
在运行过程中,需要把虚拟地址转换为物理地址。程序运行的时候,如果访问了非法内存,这时候会CORE掉,并且报SEG ERROR,就是在这个阶段探测出来的。虽然内存是分页的,但是在上层还是会维护一些段的结构以标记哪些内存是可以访问,哪些不可以。
为了提高速度,在CPU里有个部件专门负责转换,称为MMU。
想像一下最简单的转换算法,虚拟内存地址的低位表示页内的偏移,高位表示页ID,在内存里开辟一片连续区域,存储每一个页面对应的物理页面地址。
这个方法主要的问题是,太耗内存了。虚拟地址空间往往很大,会超过物理内存的大小,假设用40个BIT表示,一个页面4K,则有2^28个页面,这个消耗很大。
虚拟地址的空间很大,但是最终会用到的很少,不会超过RAM的大小。解决方案是用多层表。先把整个空间分成N段(N比较小),如果这一段里面有数据,则把这一分再切割成N份,继续递归,一般只切割4层。对于一大片没用到的空间,在表里很高的一层就统计出没有数据,不用分配出下一层的表了。为了减少多层表里节点的内存开销,上层需要把虚拟地址尽可能地连续。
这个解决方案明显的问题是,作一次转换需要多次访问内存,就算把这个表放在CACHE里,多次访问的开销还是明显的,因为这四次访问不能并行,每一步都要等上一步有结果才能进行。
所以解决方案是增加一个CACHE,称为TLB,把转换的最终结果CACHE住。
为了提高TLB的命中率,最简单的方法是,减少需要CACHE的数据,就是把内存页增大。当然这样可能会造成内存浪费,所以一般不这样做。
在MISS之后,为了减少开销,可以的把多层表的层数减少,这样步骤会变少,但是内存占用也可能增加。
前面说了这么多理论的。在作代码优化的时候,大部分的教材是不会说怎么检测TLB MISS的,用VTUNE的时候,一般也不会这样提示。用VTUNE是可以检测TLB的开销的,但是一般来说这部分开销不会是主要的。假设上层是顺序访问虚拟内存,这时候读4K数据,至多发生一次TLB MISS,这个开销占比不大。如果是随机访问,从概率上可以分析出,数据CACHE MISS的次数会比TLB MISS要多很多。而且在这种情况下,作优化,一般也就是把数据连续存放,这时候TLB的CACHE MISS也变小了。目前没碰到过需要对TLB作优化才能解决的问题。以后用VTUNE的时候,可以专门分析一下。
除了多层表,还有其他解决方案的,比如用HASH表把所有虚拟内存页跟物理内存页的映射记录下来。HASH的主要问题是数据局部性不好。当顺序访问虚拟内存的时候,查表的时候,却可能访问相距很远的两个节点。
建议继续学习:
- Linux内存点滴 用户进程内存空间 (阅读:11369)
- ps - 按进程消耗内存多少排序 (阅读:11216)
- Linux Used内存到底哪里去了? (阅读:9929)
- Linux操作系统的内存使用方法详细解析 (阅读:8842)
- linux内核研究笔记(一)内存管理 – page介绍 (阅读:8509)
- 几个内存相关面试题(c/c++) (阅读:7987)
- 内存越界的概念和调试方法 (阅读:6264)
- Innodb分表太多或者表分区太多,会导致内存耗尽而宕机 (阅读:6132)
- 必看!linux系统如何查看内存使用情况 (阅读:6132)
- 如何查看Linux 硬件配置信息 (阅读:5844)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:杨镇锋 来源: 我思故我在
- 标签: 内存 虚拟内存
- 发布时间:2011-01-25 22:41:33
- [66] Go Reflect 性能
- [66] Oracle MTS模式下 进程地址与会话信
- [65] 如何拿下简短的域名
- [59] IOS安全–浅谈关于IOS加固的几种方法
- [59] android 开发入门
- [59] 图书馆的世界纪录
- [58] 【社会化设计】自我(self)部分――欢迎区
- [53] 视觉调整-设计师 vs. 逻辑
- [47] 界面设计速成
- [47] 读书笔记-壹百度:百度十年千倍的29条法则