浅谈Linux的内存管理机制
⼀物理内存和虚拟内存
我们知道,直接从物理内存读写数据要⽐从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写⼊都在内存完成,⽽内存是有限的,这样就引出了物理内存与虚拟内存的概念。
物理内存就是系统硬件提供的内存⼤⼩,是真正的内存,相对于物理内存,在linux下还有⼀个虚拟内存的概念,虚拟内存就是为了满⾜物理内存的不⾜⽽提出的策略,它是利⽤磁盘空间虚拟出的⼀块逻辑内存,⽤作虚拟内存的磁盘空间被称为交换空间(Swap Space)。
作为物理内存的扩展,linux会在物理内存不⾜时,使⽤交换分区的虚拟内存,更详细的说,就是内核会将暂时不⽤的内存块信息写到交换空间,这样以来,物理内存得到了释放,这块内存就可以⽤于其它⽬的,当需要⽤到原始的内容时,这些信息会被重新从交换空间读⼊物理内存。
linux的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利⽤,内核会在适当的时候将物理内存中不经常使⽤的数据块⾃动交换到虚拟内存中,⽽将经常使⽤的信息保留到物理内存。
要深⼊了解linux内存运⾏机制,需要知道下⾯提到的⼏个⽅⾯:
⾸先,Linux系统会不时的进⾏页⾯交换操作,以保持尽可能多的空闲物理内存,即使并没有什么事情需要内存,Linux也会交换出暂时不⽤的内存页⾯。这可以避免等待交换所需的时间。
其次,linux进⾏页⾯交换是有条件的,不是所有页⾯在不⽤时都交换到虚拟内存,linux内核根据”最近最经常使⽤“算法,仅仅将⼀些不经常使⽤的页⾯⽂件交换到虚拟内存,有时我们会看到这么⼀个现象:linux物理内存还有很多,但是交换空间也使⽤了很多。其实,这并不奇怪,例如,⼀个占⽤很⼤内存的进程运⾏时,需要耗费很多内存资源,此时就会有⼀些不常⽤页⾯⽂件被交换到虚拟内存中,但后来这个占⽤很多内存资源的进程结束并释放了很多内存时,刚才被交换出去的页⾯⽂件并不会⾃动的交换进物理内存,除⾮有这个必要,那么此刻系统物理内存就会空闲很多,同时交换空间也在被使⽤,就出现了刚才所说的现象了。关于这点,不⽤担⼼什么,只要知道是怎么⼀回事就可以了。
最后,交换空间的页⾯在使⽤时会⾸先被交换到物理内存,如果此时没有⾜够的物理内存来容纳这些页⾯,它们⼜会被马上交换出去,如此以来,虚拟内存中可能没有⾜够空间来存储这些交换页⾯,最终会导致linux出现假死机、服务异常等问题,linux虽然可以在⼀段时间内⾃⾏恢复,但是恢复后的系统已经基本不可⽤了。
因此,合理规划和设计linux内存的使⽤,是⾮常重要的.
⼆内存的监控
作为⼀名linux系统管理员,监控内存的使⽤状态是⾮常重要的,通过监控有助于了解内存的使⽤状态,⽐如内存占⽤是否正常,内存是否紧缺等等,监控内存最常使⽤的命令有free、top等,下⾯是某个系统free的输出:
[haixigov@WEBServer ~]$ free
total        used        free      shared  buffers  cached
Mem:        16402432    16360492      41940        0    465404  12714880
-/+ buffers/cache:        3180208  13222224
Swap:        8193108        264      8192844
我们解释下输出结果中每个选项的含义:
⾸先是第⼀⾏:
total:物理内存的总⼤⼩。
used:已经使⽤的物理内存多⼩。
free:空闲的物理内存值。
shared:多个进程共享的内存值。
buffers/cached:磁盘缓存的⼤⼩。
第⼆⾏Mem:代表物理内存使⽤情况。
第三⾏(-/+ buffers/cached):代表磁盘缓存使⽤状态。
第四⾏:Swap表⽰交换空间内存使⽤状态。
free命令输出的内存状态,可以通过两个⾓度来查看:⼀个是从内核的⾓度来看,⼀个是从应⽤层的⾓度来看的。
1.从内核的⾓度来查看内存的状态
就是内核⽬前可以直接分配到,不需要额外的操作,即为上⾯free命令输出中第⼆⾏Mem项的值,可以看出,此系统物理内存有16G,空闲的内存只有41940K,也就是40M多⼀点,我们来做⼀个这样的计算:
16402432-16360492=41940
其实就是总的物理内存减去已经使⽤的物理内存得到的就是空闲的物理内存⼤⼩,注意这⾥的可⽤内存值41940并不包含处于buffers和cached状态的内存⼤⼩。
如果你认为这个系统空闲内存太⼩,那你就错了,实际上,内核完全控制着内存的使⽤情况,linux会在需要内存的时候,或在系统运⾏逐步推进时,将buffers和cached状态的内存变为free状态的内存,以供系统使⽤。
2.从应⽤层的⾓度来看系统内存的使⽤状态linux怎么读取文件
也就是linux上运⾏的应⽤程序可以使⽤的内存⼤⼩,即free命令第三⾏“(-/+ buffers/cached)”的输出,可以看到,此系统已经使⽤的内存才3180208K,⽽空闲的内存达到13222224K,继续做这样⼀个计算:
41940+(465404+12714880)=13222224
通过这个等式可知,应⽤程序可⽤的物理内存值是Mem项的free值加上buffers和cached值之和,也就是说,这个free值是包括buffers和cached项⼤⼩的,
对于应⽤程序来说,buffers/cached占有的内存是可⽤的,因为buffers/cached是为了提⾼⽂件读取的性能,当应⽤程序需要⽤到内存的时候,buffers/cached会很快地被回收,以供应⽤程序使⽤。
3.buffers与cached的异同
 在 Linux 操作系统中,当应⽤程序需要读取⽂件中的数据时,操作系统先分配⼀些内存,将数据从磁盘读⼊到这些内存中,然后再将数据分发给应⽤程序;当需要往⽂件中写数据时,操作系统先分配内存接收⽤户数据,然后再将数据从内存写到磁盘上。然⽽,如果有⼤量数据需要从磁盘读取到内存或者由内存写⼊磁盘时,系统的读写性能就变得⾮常低下,因为⽆论是从磁盘读数据,还是写数据到磁盘,都是⼀个很消耗时间和资源的过程,在这种情况下,linux引⼊了buffers和cached机制。
buffers与cached都是内存操作,⽤来保存系统曾经打开过的⽂件以及⽂件属性信息,这样当操作系统需要读取某些⽂件时,会⾸先在buffers 与cached内存区查,如果到,直接读出传送给应⽤程序,如果没有到需要数据,才从磁盘读取,这就是操作系统的缓存机制,通过缓存,⼤⼤提⾼了操作系统的性能。但buffers与cached缓冲的内容却是不同的。
buffers是⽤来缓冲块设备做的,它只记录⽂件系统的元数据(metadata)以及 tracking in-flight pages,⽽cached是⽤来给⽂件做缓冲。更通俗⼀点说:buffers主要⽤来存放⽬录⾥⾯有什么内容,⽂件的属性以及权限等等。⽽cached直接⽤来记忆我们打开过的⽂件和程序。
为了验证我们的结论是否正确,可以通过vi打开⼀个⾮常⼤的⽂件,看看cached的变化,然后再次vi这个⽂件,感觉⼀下两次打开的速度有何异同,是不是第⼆次打开的速度明显快于第⼀次呢?
接着执⾏下⾯的命令:
find /* -name  *.conf
看看buffers的值是否变化,然后重复执⾏find命令,看看两次显⽰速度有何不同。
Linux操作系统的内存运⾏原理,很⼤程度上是根据服务器的需求来设计的,例如系统的缓冲机制会把经常使⽤到的⽂件和数据缓存在cached中,linux总是在⼒求缓存更多的数据和信息,这样再次需要这些数据时可以直接从内存中取,⽽不需要有⼀个漫长的磁盘操作,这种设计思路提⾼了系统的整体性能。
三交换空间swap的使⽤
虽然现在的内存已经变得⾮常廉价,但是swap仍然有很⼤的使⽤价值,合理的规划和使⽤swap分区,对系统稳定运⾏⾄关重要。Linux 下可以使⽤⽂件系统中的⼀个常规⽂件或者⼀个独⽴分区作为交换空间使⽤。同时linux允许使⽤多个交换分区或者交换⽂件。
1.创建swap交换空间
创建交换空间所需的交换⽂件是⼀个普通的⽂件,但是,创建交换⽂件与创建普通⽂件不同,必须通过dd命令来完成,同时这个⽂件必须位于本地硬盘上,不能在⽹络⽂件系统(NFS)上创建swap交换⽂件。例如:
[root@localhost ~]# dd if=/dev/zero of=/data/swapfile bs=1024 count=65536
65536+0 records in
65536+0 records out
这样就创建⼀个有连续空间的交换⽂件,⼤⼩为60M左右,关于dd命令做简单的讲述:
if=输⼊⽂件,或者设备名称。
of=输出⽂件或者设备名称。
ibs=bytes 表⽰⼀次读⼊bytes 个字节(即⼀个块⼤⼩为 bytes 个字节)。
obs=bytes 表⽰⼀次写bytes 个字节(即⼀个块⼤⼩为 bytes 个字节)。
bs=bytes,同时设置读写块的⼤⼩,以bytes为单位,此参数可代替 ibs 和 obs。
count=blocks 仅拷贝blocks个块。
skip=blocks 表⽰从输⼊⽂件开头跳过 blocks 个块后再开始复制。
seek=blocks表⽰从输出⽂件开头跳过 blocks 个块后再开始复制。(通常只有当输出⽂件是磁盘或磁带时才有效)
这⾥的输⼊设备/dev/zero代表⼀个输出永远为0的设备⽂件,使⽤它作输⼊可以得到全为空的⽂件。
2.激活和使⽤swap
⾸先通过mkswap命令指定作为交换空间的设备或者⽂件:
[root@localhost ~]#mkswap  /data/swapfile
Setting up swapspace version 1, size = 67104 kB
[root@localhost backup]# free
total      used      free    shared    buffers    cached
Mem:      2066632    1998188      68444          0      26160    1588044
-/+ buffers/cache:    383984    1682648
Swap:      4088500    101036    3987464
从上⾯输出可知,我们指定了⼀个67104 kB的交换空间,⽽此时新建的交换空间还未被使⽤,下⾯简单介绍下mkswap命令,mkswap的⼀般使⽤格式为:
mkswap [参数] [设备名称或⽂件][交换区⼤⼩]
参数:
-c:建⽴交换区前,先检查是否有损坏的区块。
-v0:建⽴旧式交换区,此为预设值。
-v1:建⽴新式交换区。
交换区⼤⼩:指定交换区的⼤⼩,单位为1024字节。
设置交换分区后,接着通过swapon命令激活swap:
[root@localhost ~]#/usr/sbin/swapon /data/swapfile
[root@localhost backup]# free
total      used      free    shared    buffers    cached
Mem:      2066632    1997668      68964          0      27404    1588880
-/+ buffers/cache:    381384    1685248
Swap:      4154028    100976    4053052
通过free命令可以看出,swap⼤⼩已经由4088500k变为4154028k,相差的值是60M左右,刚好等于我们增加的⼀个交换⽂件⼤⼩,这说明新增的交换分区已经可以使⽤了,但是如果linux重启,那么新增的swap空间将变得不可⽤,因此需要在/etc/fstab中添加⾃动加载设
置:
/data/swapfile  none  swap  sw 0 0
如此以来,linux在重启后就可以实现⾃动加载swap分区了。其实linux在启动过程中会执⾏“swapon -a”命令,此命令会加载列在/etc/fstab中的所有交换空间。
3.移除swap
通过swapoff即可移除⼀个交换空间
[root@localhost ~]#/usr/sbin/swapoff /data/swapfile
其实也可以通过“swapoff -a”移除在/etc/fstab中定义的所有交换空间,这⾥的“swapoff -a”与上⾯提到的“swapon -a”对应。执⾏“swapoff -a”后,free命令输出如下:
[root@localhost backup]# free
total      used      free    shared    buffers    cached
Mem:      2066632    2048724      17908          0      30352    1642748
-/+ buffers/cache:    375624    1691008
Swap:            0          0          0