

linux内存管理卷帙浩繁,本文只能层层递进地带你领略冰山轮廓,经过本文你将了解到如下内容:linux
为何须要管理内存web
linux段页管理机制算法
内存碎片的产生机理缓存
为何须要管理内存
老子的著名观点是无为而治,简单说就是不过多干预而充分依靠自觉就能够有条不紊地运做,理想是美好的,现实是残酷的。微信
在linux系统中若是以一种原始简单的方式管理内存是存在一些问题的,咱们来看几个场景。app
内存管理的问题
进程空间隔离问题 假如如今有ABC三个进程运行在linux的内存空间,设定os给进程A分配的地址空间是0-20M 进程B地址空间30-80M,进程C地址空间90-120M,如图:编辑器
在某些时候程序空间的访问可能出现问题,好比进程A访问了属于进程B的空间,进程B访问了属于进程C的空间,甚至修改了空间的值,这样就会形成混乱和错误,因此实际中是不容许这种状况发生的。ide
内存效率和内存不足问题性能
机器的内存是有限资源,而进程数量是没法肯定的,若是在某些时候已经启动的进程占据了全部内存空间,此时就没法启动新进程了,由于没有新内存可分配了,可是咱们观察到已经启动的进程有时候是在睡大觉,也就是给了内存也不用,这样效率确实是有点低,因此咱们须要一个管理员把不用的内存倒腾出来,另外连续内存实在是很珍贵,不少时候咱们无法有效及时地分配连续内存,所以虚拟化和离散化可能会有效提升内存的使用率。flex
程序定位调试和编译运行问题
因为程序运行时的位置时不肯定的,咱们在定位问题、调试代码、编译执行时都会存在不少问题,咱们但愿每一个进程有一致且完整的地址空间,一样的起始位置放置了堆、栈以及代码段等,从而简化编译和执行过程当中的 linker 连接器、loader 加载器的使用。
虚拟地址空间
为了解决上述的一些问题,linux系统引入了虚拟空间的概念,虚拟化的出现和硬件有密不可分的联系,能够说是软硬件组合的结果,虚拟地址空间就是在程序和物理空间所增长的中间层,这也是内存管理的重点。
磁盘 disk 做为一种大容量的存储也做为"内存"的一部分参与程序的运行,内存管理系统会将不经常使用非活跃内存进行页面换出,能够认为内存是磁盘的缓存,内存中保留了活跃的数据,从而间接扩展了有限的物理内存空间,这部分空间称为虚拟内存是相对于物理内存而言的。
段页管理机制
本文并不深刻地将分段管理内存和分页管理内存,由于将这些细节的优秀文章不少,感兴趣的使用搜索引擎一键即达。
段页机制也不是一蹴而就的,经历了单纯物理分段、单纯分页、单纯逻辑分段等阶段,最终演进出来了分段和分页结合的内存管理方式,段页结合得到了分段和分页的优点也避免了单一模式的弊端,是一种比较好的管理模式。
本文对于段页管理机制只想通俗地说明一些概念,段页管理机制是分段式管理和分页式管理的组合,段式管理是逻辑上的管理方式,分页管理是偏物理上的管理方式。
计算机里面的一些技术和实现均可以在现实生活中找到缩影,所谓艺术和科技源自生活大概就是这个意思吧。
举个栗子:
在进行居民户籍管理时都会有区县市的概念,可是实际上并无这种实体,都是逻辑上的,增长了这些行政单位以后可让地址管理更加直接。
对于咱们居民来讲惟一的实体就是本身的房子住所,这是物理上的单位,是真实存在的,这也是最基本的单位。
对比linux段页时管理来讲,段是逻辑上的单位至关于区县市的概念,页是物理上的单位至关于小区/房屋的概念,这样就方便不少。
多级页表也很好理解,总的物理内存假若有4GB,页大小为4KB,那么就总共有2^20个页,数量仍是很是大的,这样编号来创建索引寻址比较不方便,因此引入多级页表,来减小存储便于管理。
段页机制加持下的逻辑地址和物理地址的映射关系简图,也就是虚拟地址到物理地址的对应关系:
内存管理单元( MMU Memory Management Unit )是硬件层组件,主要提供将虚拟地址映射为物理地址。
MMU 的工做流程:CPU 生成逻辑地址交给分段单元,分段单元进行处理将逻辑地址转换为线性地址,再线性地址交给分页单元,分页单元根据页表映射转换内存物理地址,其中可能出现缺页中断。
缺页中断( Page Fault )是只当软件试图访问一个虚拟地址时,通过段页转换为物理地址以后,此时发现该页并无在内存中,这时 cpu 就会报出中断,再进行相关虚拟内存的调入工做或者分配工做,若是出现异常也可能直接中断。
物理内存和内存碎片
前面说的段页管理机制算是虚拟空间的部分,然而linux内存管理的另一个重要部分就是物理内存的管理了,也就是如何分配和回收物理内存,这就涉及到一些内存分配算法和分配器。
物理内存分配器
分配器和分配算法就像公司财务,内存就像公司资金,如何把资金合理使用是财务的本职工做,如何把物理内存合理使用是分配器的份内之事。
内存碎片分类和机理
若是咱们不知道内存碎片是什么,试想一下咱们常说的碎片化的时间,也就是那些虽然空闲可是没有被利用的时间,其实内存也是如此。
不管是时间仍是内存被碎片化以后都没法被有效利用,所以合理管理减小碎片对咱们来讲是相当重要的,这也是物理内存分配算法和分配器的研究重点。
按照碎片的位置和产生缘由,内存碎片分为外部碎片和内部碎片,咱们看下这两种碎片的直观展现:
从图中能够知道,外部碎片是进程与进程间未分配的内存空间,外部碎片的出现和进程频繁的分配和释放内存有直接关系,这个很好理解,模拟一下分配不一样空间的进程不一样时间释放就能够看到外部碎片的产生了。
内部碎片主要由于分配器粒度问题以及一些地址限制致使实际分配的内存大于所需内存,这样在进程内部就会出现内存空洞。
虽然虚拟地址让进程使用的内存在物理内存上是离散的,可是不少时候进程须要必定量连续物理内存,若是大量碎片存在,就会形成没法启动进程的问题,如图Process7须要一块连续的物理内存却没法被分配:
在Linux系统下,监控内存经常使用的命令是free、top等,下面是一个free命令的执行结果:
要了解Linux的内存管理,首先要明白上例中各个名词的意义:
total:物理内存的总大小。
used:已经使用的物理内存多小。
free:空闲的物理内存值。
shared:多个进程共享的内存值。
buffers / cached:用于磁盘缓存的大小(这部分是从物理内存中划出来的)。
第二行Mem:表明物理内存使用状况。
第三行(-/+ buffers/cached):表明磁盘缓存使用状态。
第四行:Swap表示交换空间内存使用状态(这部分其实是从磁盘上虚拟出来的逻辑内存)。
free命令输出的内存状态,能够从两个角度来看:内核角度、应用层角度。
1. 从内核角度来查看内存的状态:
就是内核目前能够直接分配到,不须要额外的操做,即free命令第二行 Mem 的输出。从上例中可见,41940 + 16360492 = 16402432,也就是说Mem行的 free + used = total,注意,这里的free并不包括buffers和cached。
2. 从应用层角度来查看内存的状态:
也就是Linux上运行的程序可使用的内存大小,即free命令第三行 -/+ buffers/cache 的输出。再来作一个计算41940+(465404+12714880)=13222224,即Mem行的free + buffers + cached = -/+ buffers/cache行的free,也就是说应用可用的物理内存值是Mem行的free、buffers和cached三者之和,可见-/+ buffers/cache行的free是包括buffers和cached的。
对于应用程序来讲,buffers/cached占有的内存是可用的,由于buffers/cached是为了提升文件读取的性能,当应用程序须要用到内存的时候,buffers/cached会很快地被回收,以供应用程序使用。
物理内存和虚拟内存 物理内存就是系统硬件提供的内存大小,是真正的内存。在linux下还有一个虚拟内存的概念,虚拟内存就是为了知足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存,用做虚拟内存的磁盘空间被称为 交换空间(Swap Space) 。
linux的内存管理采起的是分页存取机制,为了保证物理内存能获得充分的利用,内核会在适当的时候将物理内存中不常用的数据块自动交换到虚拟内存中,而将常用的信息保留到物理内存。而进行这种交换所遵循的依据是“LRU”算法(Least Recently Used,最近最少使用算法)。
最后介绍下Buffers和Cached有什么用
在任何系统中,文件的读写都是一个耗时的操做,当应用程序须要读写文件中的数据时,操做系统先分配一些内存,将数据从磁盘读入到这些内存中,而后应用程序读写这部份内存数据,以后系统再将数据从内存写到磁盘上。若是是大量文件读写甚至重复读写,系统读写性能就变得很是低下,在这种状况下,Linux引入了缓存机制。
buffers与cached都是从物理内存中分离出来的,主要用于实现磁盘缓存,用来保存系统曾经打开过的文件以及文件属性信息,这样当操做系统须要读取某些文件时,会首先在buffers与cached内存区查找,若是找到,直接读出传送给应用程序,不然,才从磁盘读取,经过这种缓存机制,大大下降了对磁盘的IO操做,提升了操做系统的数据访问性能。而这种磁盘高速缓存则是基于两个事实:第一,内存访问速度远远高于磁盘访问速度;第二,数据一旦被访问,就颇有可能短时间内再次被访问。
另外,buffers与cached缓存的内容也是不一样的。buffers是用来缓冲块设备作的,它只记录文件系统的元数据(metadata)以及 tracking in-flight pages,而cached是用来给文件作缓冲。更通俗一点说:buffers主要用来存放目录里面有什么内容,文件的属性以及权限等等。而cached直接用来记忆咱们打开过的文件和程序。
为了验证咱们的结论是否正确,能够经过vi打开一个很是大的文件,看看cached的变化,而后再次vi这个文件,感受一下是否是第二次打开的速度明显快于第一次?
接着执行下面的命令:
find /* -name *.conf
看看buffers的值是否变化,而后重复执行find命令,看看两次显示速度有何不一样。
Linux内存管理的哲学
Free memory is wasted memory.
Linux的哲学是尽量多的使用内存,减小磁盘IO,由于内存的速度比磁盘快得多。 Linux老是在力求缓存更多的数据和信息,内存不够时,将一些不常用的数据转移到交换分区(Swap Space)中以释放更多可用物理内存,固然,若是交换分区的数据再次被读写时,又会被转移到物理内存中,这种设计思路提升了系统的总体性能。而Windows的处理方式是,内存和虚拟内存一块儿使用,不是之内存操做为主,结果就是IO的负担比较大,可能拖慢处理速度。
Linux和Windows在内存管理机制上的区别
在Linux系统使用过程当中,你会发现,不管你的电脑内存配置多么优越,仍然不时的发生可用内存吃紧的现象,感受内存不够用了,其实否则。这是Linux内存管理的优秀特性,不管物理内存有多大,Linux都将其充分利用,将一些程序调用过的硬盘数据缓存到内存,利用内存读写的高速性提升系统的数据访问性能。而Window只在须要内存时,才为应用分配内存,不能充分利用大容量的内存空间。 换句话说,每增长一些内存,Linux都能将其利用起来,充分发挥硬件投资带来的好处,而Windows只将其做为摆设。
因此说,通常咱们不须要太关注Linux的内存占用状况,而若是Swap占用率一直居高不下的话,就颇有可能真的是须要扩展内存了。
夯实基础,关注前沿,娱乐生活
掌握更多前沿技术,获取更多笑点
请关注--------喘口仙氣
本文分享自微信公众号 - 喘口仙氣(gh_db8538619cdd)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。