相信有许多同学都对free命令中的buffers cached十分不理解,今天笔者就对free命令机器结果做一个详细的剖析。

   

以下是笔者在虚拟机上运行的debian系统的free情况。该虚拟机内存只有128M,同时分配了256M的SWAP交换区。

   

               total used free shared buffers cached

Mem: 124788 113432 11356 0 15308 75568

-/+ buffers/cache: 22556 102232

Swap: 245752 20 245732

   

第一行 (可以理解为从操作系统的角度来看内存分配)

   

total

总物理内存大小。

used

已分配的大小,注意,对操作系统来说任何被使用的内存都是used。

free

未被分配的物理内存大小。

shared

共享内存大小,主要用于进程间通信,例如Oracle会使用上GB的共享内存。

buffers

主要用于块设备数据缓冲,例如记录文件系统的metadata(目录、权限等等信息)。

cached

主要用于文件内容缓冲

   

# 这里补充一下关于文件系统的常识 ^_^

# 文件系统实际上可以粗略的划分为两个部分:

# (1)metadata:即通常说的元数据,包括目录结构、文件的名字、大小、修改时间、权限等等信息。

# (2)filedata:即文件中真正存储的内容。

# 由于计算机中各个部件之间的速度相差很大,通常情况下CPU的cache最快,其次是内存,最慢的自然就是硬盘等外部设备了。

# 而越慢的设备越廉价,所以硬盘就被用来存储大量数据(有一天内存不要钱了大家就不用在被buffer、cache这个东东折磨了 <( ̄︶ ̄)>)。

# 所以,文件系统就被放在了硬盘上(不可避免的悲剧~~)。但是由于硬盘速度实在太慢了,为了改善IO性能,最终就诞生了"缓存"这一概念。

# "缓存"实际上就是在内存中划分一块区域作为硬盘和进程之间的缓冲区域,写进程把数据写到这里然后就干其他事情去了,读进程需要时先在这里找,找不到再去找硬盘,这样就大大提高了读写效率,同时缩短了IO等待时间,否则你在linux上运行man iptables 这样的命令的时候每次都会等N久。。。

# 这里还有一个"物理内存"和"虚拟内存"的概念,这个概念比较难讲,大家去google一些大牛的帖子看吧,涉及的东西太多了。。。。

   

所以,这里,buffer实际上是用来存储了文件系统的元数据(这样我们每次ls就会很快了 ^_^),而cache则缓存了近期读写过的文件的内容(第一次读文件会很慢,以后就会很快,就是因为有cache的存在),把这个理解了free命令就理解了大半了。

   

继续讲。。。

   

第二行 (可以理解为从应用程序的角度来看内存分配)

   

-/+ buffers/cached: 22556 102232

这里的 -/+ 实际上分别指的是 - buffers/cached 和 + buffers/cached 两个部分。

   

- buffers/cached

= used(第一行) - buffers - cached

实际上是程序当前"真实使用"的"物理内存"的大小。

+ buffers/cached

= buffers + cached

两个加起来可以理解为"暂时借给"系统作为"缓冲区"使用的内存大小。

   

大家做一下简单的加减法就清楚了:

从应用多角度来说,实际上系统还可以分配给他的内存有这么多:11356(free) + 15308(buffers) + 75568(cached)= 102232(free)

而系统所拥有的总的物理内存大小 113432 = 22556( - buffers/cached) + 102232 (+ buffers/cached)

   

所以,第一行的数据实际上是从操作系统角度来看的。

对于操作系统来说已分配的内存表示已经被某些数据所占据了,但是具体这些数数据是用来做什么的他不会去理会。

实际上正如前面所说,这部分物理内存被拿来做"缓存"了。

   

但是,是不是应用就不能使用了呢?

当然不是!!!!

不然我也不用写了,大家都懂了。。。

   

前面说到buffers和cached这部分内存是"借给"操作系统使用的,之所以说是"借的",这里主要原因还在于"虚拟内存"与"物理内存"的区别。

对于应用来说,我申请了1000KB的内存,操作系统同意了,给程序一个地址,告诉他你要的内存在这里,然后程序就拿着这个地址去用了。

但是实际上大多数时候程序不会立刻将这些内存使用掉,而是一点一点的使用,所以,在没有使用之前,系统就能将这一部分物理内存拿去做其他事情已提升整个系统的性能,比如说这里的"缓存"。

当然,这样理解"虚拟内存"是非常片面的,实际情况比这要复杂得多,比如说这还涉及到程序的运行空间、代码的编译、链接、加载等等,必须结合起来才能解释清楚为什么需要虚拟内存,实际上"虚拟内存"是一个抽象的概念的实现,大大简化了操作系统和应用的设计复杂度。

虽然要讲的太多太多,但是,今天这样理解"虚拟内存"在这里也够用了。 ^_^

在这里操作系统就相当于"借"了一部分内存出去以提高系统的IO性能。

   

对于"虚拟内存"和"物理内存"可以通过ps aux命令简单看一下:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

root 1471 0.0 0.3 2152 428 ? S 15:55 0:00 /usr/bin/daemon /etc/init.d/mpt-statusd check_mpt

root 1474 0.0 0.4 1748 556 ? S 15:55 0:00 /bin/sh /etc/init.d/mpt-statusd check_mpt

   

VSZ这一列显示的就是对应程序所分配的"虚拟内存"大小,而RSS则是程序实际使用的内存,VSZ实际是比RSS要大的,说明程序没有使用到他所申请的那么多内存,如果分配出去了肯定是闲的蛋疼。。。你的机器也不能像现在这样一边跑QQ一边看网页。。。开个chrome就完蛋了。。

   

细心的同学会发现,上面讲的这个"借"的过程和银行的业务很相似,大家把手里的现钱存到银行去,银行给我们一张卡,卡上有个卡号,银行说"凭这个卡和密码你就可以随时来取钱了"。然后我们就放心的把钱存在银行里,等需要钱的时候就拿着卡去取钱,而银行这时候也能拿着我们的钱去投资修桥补路。

唯一的区别可能就是银行有利息,这里么有~~~~~

   

扯远了,回到主题上。

   

好,既然我们说这个内存是"借"来的,那当然有程序会拿着地址过来要内存的时候(就跟取钱一样)。

这时候操作系统就会从第一行的free这里去找空闲内存分给程序用。

但是大家肯定发现了,大部分的内存是被buffers和cached占用了,万一来个需求大的内存的时候怎么办?

答案很简单嘛,把放出去的"贷款"收回来呗~~~~

那就从buffers和cached中释放内存,同时将所释放空间中的数据回写到硬盘上,防止数据丢失。

   

再插一句,要是buffers和cached也没了怎么办?那"银行"就只有从其他地方"借钱"来还了~~~

这次"借"就是从硬盘借了,也就是我们所说的分配SWAP空间,将一部分内存页面换到SWAP空间中。

当然实际的处理过程系统不会等到buffers和cached回收完才使用SWAP空间的,比你想象的要轻易得多,因为有时候缩小"缓存"的性能代价比使用SWAP空间更高,Linux系统还是很smart的~~~

   

回来继续说。

那什么时候系统会开始回收buffers和cached部分的内存呢?

这里要看一下数据:

root@debian01:~# cat /proc/meminfo

MemTotal: 124788 kB

MemFree: 11596 kB

Buffers: 15332 kB

Cached: 75568 kB

SwapCached: 20 kB

Active: 54884 kB

Inactive: 45564 kB

Active(anon): 2124 kB

Inactive(anon): 7560 kB

Active(file): 52760 kB

Inactive(file): 38004 kB

Unevictable: 0 kB

Mlocked: 0 kB

HighTotal: 0 kB

HighFree: 0 kB

LowTotal: 124788 kB

LowFree: 11596 kB

SwapTotal: 245752 kB

SwapFree: 245732 kB

Dirty: 0 kB

Writeback: 0 kB

AnonPages: 9544 kB

Mapped: 5884 kB

Shmem: 136 kB

Slab: 8784 kB

SReclaimable: 4940 kB

SUnreclaim: 3844 kB

KernelStack: 528 kB

PageTables: 456 kB

NFS_Unstable: 0 kB

Bounce: 0 kB

WritebackTmp: 0 kB

CommitLimit: 308144 kB

Committed_AS: 43272 kB

VmallocTotal: 897016 kB

VmallocUsed: 6344 kB

VmallocChunk: 879908 kB

HardwareCorrupted: 0 kB

HugePages_Total: 0

HugePages_Free: 0

HugePages_Rsvd: 0

HugePages_Surp: 0

Hugepagesize: 4096 kB

DirectMap4k: 16384 kB

DirectMap4M: 114688 kB

   

meminfo的数据比较多,这里就不细讲了,我们只关注一个数据。

LowFree: 11596 kB

实际上当free部分的内存小于这个值的时候,系统就会考虑是否需要回收"缓存"部分的物理内存,当然这不是绝对的,这可以作为一个参考阀值。

   删除线这段话有问题,正在研究

OK,最后一部分。

   

说了这么多,那么到底有没有办法强制释放呢??

当然有啊!!!银行欠你钱你会不去要???

   

话说办法其实很简单,在控制台执行以下命令即可:

echo 3 > /proc/sys/vm/drop_caches

这里的"3"表示释放所有buffers和cached中能释放的部分。

   

root@debian01:~# echo 3 > /proc/sys/vm/drop_caches

root@debian01:~# free

          total used free shared buffers cached

Mem: 124788 26764 98024 0 148 6144

-/+ buffers/cache: 20472 104316

Swap: 245752 20 245732

   

手工释放以后大家可以测试一下,运行几次类似以下这些命令,会明显发现又涨上去了。。。

ls -la /dev/

find / -name *.sh

man iptables

   

root@debian01:~# free

             total used free shared buffers cached

Mem: 124788 87368 37420 0 30692 25512

-/+ buffers/cache: 31164 93624

Swap: 245752 20 245732

   

OK,到这里free相关的东西就讲的差不多了。。。

写了好久~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~