Linux中的Buffer Cache和Page Cache echo 3 > /proc/sys/vm/drop_caches Slab内存管理机制 SLUB内存管理机制

时间:2022-05-17 03:16:11

Linux中的Buffer Cache和Page Cache echo 3 > /proc/sys/vm/drop_caches   Slab内存管理机制 SLUB内存管理机制

http://wenku.baidu.com/view/dd677d2fcfc789eb172dc868.html

http://bbs.chinaunix.net/thread-3759086-1-1.html

http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=4189715&extra=page%3D1%26filter%3Dauthor%26orderby%3Ddateline%26orderby%3Ddateline

了解下flush进程! [复制链接]
http://bbs.chinaunix.net/thread-3759086-1-1.html
top中看到了:
403 root 20 0 0 0 0 S 0.3 0.0 0:01.34 flush-8:16
复制代码
这是个什么进程?

难怪我服务器在IO数据特别大的时候,这个进程使用率偏高,但是这儿有个疑问!在文件复制的状况下,内存里面是不是大量充斥着 文件数据?而之前真正需要保存的却没有保存到(被这个文件数据给flush掉)?

该保存肯定会保存 只不过早晚的事情 可以手动 sync

http://bbs.chinaunix.net/thread-2174038-1-1.html

-----------------------------------------------
为了提高磁盘存取效率,Linux做了一些精心的设计,除了对dentry进行缓存(用于VFS,加速文件路径名到inode的转换),还采取了两种主要Cache方式:

Buffer CachePage Cache。前者针对磁盘块的读写,后者针对文件inode的读写。这些Cache有效缩短了 I/O系统调用(比如read,write,getdents)的时间。

那么有人说过段时间,linux会自动释放掉所用的内存。等待一段时间后,我们使用free再来试试,看看是否有释放?
引用
[root@server test]# free -m
total used free shared buffers cached
Mem: 249 244 5 0 8 174
-/+ buffers/cache: 61 188
Swap: 511 0 511

似乎没有任何变化。(实际情况下,内存的管理还与Swap有关)

那么我能否手动释放掉这些内存呢?回答是可以的!

二、手动释放缓存
/proc是一个虚拟文件系统,我们可以通过对它的读写操作做为与kernel实体间进行通信的一种手段。也就是说可以通过修改/proc中的文件,来对当前kernel的行为做出调整。那么我们可以通过调整/proc/sys/vm/drop_caches来释放内存。操作如下:
引用
[root@server test]# cat /proc/sys/vm/drop_caches
0

首先,/proc/sys/vm/drop_caches的值,默认为0。
引用
[root@server test]# sync

手动执行sync命令(描述:sync 命令运行 sync 子例程。如果必须停止系统,则运行sync 命令以确保文件系统的完整性。sync 命令将所有未写的系统缓冲区写到磁盘中,包含已修改的 i-node、已延迟的块 I/O 和读写映射文件
引用
[root@server test]# echo 3 > /proc/sys/vm/drop_caches
[root@server test]# cat /proc/sys/vm/drop_caches
3

将/proc/sys/vm/drop_caches值设为3
引用
[root@server test]# free -m
total used free shared buffers cached
Mem: 249 66 182 0 0 11
-/+ buffers/cache: 55 194
Swap: 511 0 511

再来运行free命令,会发现现在的used为66MB,free为182MB,buffers为0MB,cached为11MB。那么有效的释放了buffer和cache。

◎ 有关/proc/sys/vm/drop_caches的用法在下面进行了说明
引用
/proc/sys/vm/drop_caches (since Linux 2.6.16)
Writing to this file causes the kernel to drop clean caches,
dentries and inodes from memory, causing that memory to become free.

To free pagecache, use echo 1 > /proc/sys/vm/drop_caches;   小米兼职DBA http://www.cnblogs.com/MYSQLZOUQI/p/4857437.html
to free dentries and inodes, use echo 2 > /proc/sys/vm/drop_caches;
to free pagecache, dentries and inodes, use echo 3 >/proc/sys/vm/drop_caches.

Because this is a non-destructive operation and dirty objects are not freeable, the user should run sync first.

三、我的意见
上述文章就长期以来很多用户对Linux内存管理方面的疑问,给出了一个比较“直观”的回复,我更觉得有点像是核心开发小组的妥协。
对于是否需要使用这个值,或向用户提及这个值,我是有保留意见的:
引用
1、从man可以看到,这值从2.6.16以后的核心版本才提供,也就是老版的操作系统,如红旗DC 5.0、RHEL 4.x之前的版本都没有;
2、若对于系统内存是否够用的观察,我还是原意去看swap的使用率和si/so两个值的大小;

用户常见的疑问是,为什么free这么小,是否关闭应用后内存没有释放?
但实际上,我们都知道这是因为Linux对内存的管理与Windows不同,free小并不是说内存不够用了,应该看的是free的第二行最后一个值:
引用
-/+ buffers/cache: 58 191

这才是系统可用的内存大小。
实际项目中告诉我们,如果因为是应用有像内存泄露、溢出的问题,从swap的使用情况是可以比较快速可以判断的,但free上面反而比较难查看。
相反,如果在这个时候,我们告诉用户,修改系统的一个值,“可以”释放内存,free就大了。用户会怎么想?不会觉得操作系统“有问题”吗?
所以说,我觉得既然核心是可以快速清空buffer或cache,也不难做到(这从上面的操作中可以明显看到),但核心并没有这样做(默认值是0),我们就不应该随便去改变它。
一般情况下,应用在系统上稳定运行了,free值也会保持在一个稳定值的,虽然看上去可能比较小。
当发生内存不足、应用获取不到可用内存、OOM错误等问题时,还是更应该去分析应用方面的原因,如用户量太大导致内存不足、发生应用内存溢出等情况,否则,清空buffer,强制腾出free的大小,可能只是把问题给暂时屏蔽了。

我觉得,排除内存不足的情况外,除非是在软件开发阶段,需要临时清掉buffer,以判断应用的内存使用情况;或应用已经不再提供支持,即使应用对内存的时候确实有问题,而且无法避免的情况下,才考虑定时清空buffer。(可惜,这样的应用通常都是运行在老的操作系统版本上,上面的操作也解决不了)。O(∩_∩)O哈哈~
visitor
2009/02/25 11:28
完全没必要这样做,即使内存全被cache满了,运行一个大程序试试,绝不会有什么“内存不足”的情况,需要多少内存就从cache释放多少内存。

cache的好处可以减少很多硬盘访问,我的一块老硬盘,用windows的时候每打开一个程序硬盘都要狂响一阵,和拖拉机有一比,但用linux的时候硬盘非常安静!


 

记一次内存占用问题的调查过程
http://blog.atime.me/research/linux-ate-my-memory.html

最近在维护一台CentOS服务器的时候,发现内存无端"损失"了许多,free和ps统计的结果相差十几个G,搞的我一度又以为遇到灵异事件了,后来Google了许久才搞明白,特此记录一下,以供日后查询。

虽然天天都在用Linux系统办公,其实对它的了解也不过尔尔。毕业几年才迈入"知道自己不知道"的境界,我觉得自己丝毫没有愧对万年吊车尾这个称号 :(
问题描述和初步调查

同事说有一台服务器的内存用光了,我连上去用free看了下,确实有点怪。

$ free -g
             total       used       free     shared    buffers     cached
Mem:            15         15          0          0          2          0
-/+ buffers/cache:         12          2
Swap:           17          0         17

这台服务器有16G内存,但是结果显示除了2G左右的文件Buffer缓存外,其余十几G都被确确实实的用光了。(free按1024进制计算,总内存可能比实际偏小)

这里大概介绍下free结果的含义:
/     total     used     free     shared     buffers     cached
Mem     总物理内存     当前使用的内存(包括slab+buffers+cached)     完全没有使用的内存     进程间共享的内存     缓存文件的元数据1     缓存文件的具体内容1
-/+ buffers/cache         当前使用的内存(不包括buffers+cached,但包括slab)     未使用和缓存的内存(free+buffers+cached)             
Swap     总的交换空间     已使用的交换空间     未使用的交换空间

然后top看了下,没有特别吃内存的程序。用ps大概统计下所有程序占用的总内存:

$ ps aux | awk '{mem += $6} END {print mem/1024/1024}'
0.595089

结果显示所有进程占用的内存还不到1G,实际上,因为free, ps的统计方式的差别和Copy-on-write和Shared libraries等内存优化机制的存在,这两者的统计结果通常是不一样的。但是一般情况下绝对不会相差十几个G,肯定是有什么隐藏的问题,Google了许久后发现,free没有专门统计另一项缓存: Slab。
Slab简介和进一步调查

Slab Allocation是Linux 2.2之后引入的一个内存管理机制,专门用于缓存内核的数据对象,可以理解为一个内核专用的对象池,可以提高系统性能并减少内存碎片。(Linux 2.6.23之后,SLUB成为了默认的allocator。)

查看Slab缓存

$ cat /proc/meminfo

其中,Slab相关的数据为

Slab:             154212 kB
SReclaimable:      87980 kB
SUnreclaim:        66232 kB

SReclaimable(Linux 2.6.19+)都是clean的缓存,随时可以释放。回到之前的内存问题,我查了下那台服务器上Slab占用的内存:

$ cat /proc/meminfo | grep Slab
Slab:         12777668 kB

12G的Slab缓存,有意思的是free把Slab缓存统计到了used memory中,这就是之前那个问题的症结所在了。

另外,还可以查看/proc/slabinfo(或使用slabtop命令)来查看Slab缓存的具体使用情况。结果发现,ext3_inode_cache和dentry_cache占用了绝大部分内存。

考虑到这台服务器会频繁地用rsync同步大量的文件,这个结果也并不意外。
解决问题

先说明一下,如果问题仅仅是Slab占用了太多的内存(SReclaimable),那么通常不需要太操心,因为这根本不是个问题(如果是SUnreclaim太多且不断增长,那么很有可能是内核有bug)。但是,如果是因为Slab占用内存太多而引起了其他的问题,建议继续阅读。
清除Slab可回收缓存

通过/proc/sys/vm/drop_caches这个配置项,我们可以手动清除指定的可回收缓存(SReclaimable)2。

echo 2 > /proc/sys/vm/drop_caches

上面的命令会主动释放Slab中clean的缓存(包括inode和dentry的缓存),然后再free -g一下,未使用的内存陡增了十几个G。。。

需要注意的是,手动清除缓存可能会在一段时间内降低系统性能。原则上不推荐这么做,因为如果有需要,系统会自动释放出内存供其他程序使用。

另外,手动清除Slab缓存是一个治标不治本的办法。因为问题不在Slab,而在于我们那个会引起Slab缓存飙涨的进程(我这里应该是rsync)。实际操作的时候发现,清除缓存一段时间后,Slab缓存很快又会“反弹”回去。如果需要治本,要么搞定问题进程,要么修改系统配置。
调整系统vm配置

风险预警: 调整以下系统配置可能会对系统性能造成负面影响,请仔细测试并谨慎操作。

/etc/sysctl.conf里有几个对内存管理影响比较大的配置,以下配置项的文档见vm.txt。
vm.vfs_cache_pressure

系统在进行内存回收时,会先回收page cache, inode cache, dentry cache和swap cache。vfs_cache_pressure越大,每次回收时,inode cache和dentry cache所占比例越大3。

vfs_cache_pressure默认是100,值越大inode cache和dentry cache的回收速度会越快,越小则回收越慢,为0的时候完全不回收(OOM!)。

linux io caches

图片取自The Linux Kernel's VFS Layer
vm.min_free_kbytes

系统的"保留内存"的大小,"保留内存"用于低内存状态下的"atomic memory allocation requests"(eg. kmalloc + GFP_ATOMIC),该参数也被用于计算开始内存回收的阀值,默认在开机的时候根据当前的内存计算所得,越大则表示系统会越早开始内存回收。

min_free_kbytes过大可能会导致OOM,太小可能会导致系统出现死锁等问题。

vm.swappiness
该配置用于控制系统将内存swap out到交换空间的积极性,取值范围是[0, 100]。swappiness越大,系统的交换积极性越高,默认是60,如果为0则不会进行交换。
参考资料

man proc
    The Linux Kernel's VFS Layer
    The VFS in Linux Kernel V2.4
    openSUSE: System Analysis and Tuning Guide, Chapter 15. Tuning the Memory Management Subsystem
    Red Hat Enterprise Linux, 5.5 Tuning Virtual Memory
    Odd behavior
    Wikipedia:Slab allocation

阅读资料

Linux System IO Monitoring
    Paging
    Understanding the Linux Virtual Memory Manager
    Understanding the Linux Kernel, 3rd Edition

脚注

1 2

Red Hat Enterprise Linux,5.1 Checking the Memory Usage,引用于2014-12-12。

Linux kernel documentation, sysctl#vm,引用于2014-12-12。

@TODO: 需要查看相关内核代码来确认,不过看vm.txt里的描述应该是这个意思。
Linux中的Buffer Cache和Page Cache echo 3 > /proc/sys/vm/drop_caches   Slab内存管理机制 SLUB内存管理机制


如果swap都是0kb或4kb,则是正常现象,否则说明该进程的内存已经被交换出去了
cat /proc/进程号/smaps |grep -i swap
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB

比如redis的进程号是889,redis不能使用swap,否则性能会有影响
cat /proc/889/smaps |grep -i swap
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB