嵌入式Linux系统Cache内存占用过高问题的分析

问题背景:

        在嵌入式Linux系统产品稳定性测试过程中,我们最关心也是最重要的问题是内存泄漏问题。

        一般嵌入式产品内存容量比较有限,我们除了分析代码层次的内存泄漏缺陷外,还实时监测系统运行的内存状态。以免过度使用内存导致系统将进程kill掉的情况。本文主要分析下Cache内存占用的原因,解决办法以及对系统运行的影响;

问题分析:

在嵌入式Linux系统中使用free命令可以看到如下信息:

# free
             total       used       free     shared    buffers     cached
Mem:        247400     123764     123636      33236       7728      63292
-/+ buffers/cache:      52744     194656
Swap:            0          0          0
# 

可以简单看到内存的总容量、free容量、缓存占用的buffers、cached容量;

Linux下内存占用多的原因和机制为:

        当linux第一次读取一个文件运行时,一份放到一片内存中cache起来,另一份放入运行程序的内存中,正常运行,当程序运行完,关闭了,cache中的那一分却没有释放,第二次运行的时候,系统先看看在内存中是否有一地次运行时存起来的cache中的副本,如果有的话,直接从内存中读取,那样,速度就快多了。

        说明这种情况的很典型的例子是启动firefox,由于firefox程序很大,因此第一次读取运行的时候很慢,尤其在速度不快的机器上,但是当你彻底关闭了firefox,ps看不到一个firefox进程,第二次再启动的时候就比第一次明显快很多,这是由于这次系统是直接从cache中读取的firefox来运行,并不是从磁盘上读取的。

        再有一个例子:我们频繁使用的ls命令等基本命令,你运行的时候根本看不到硬盘灯闪,因为这些常用的命令都是再第一次运行后就保存在cache中的,以后就一直从内存中读出来运行。

        如果cache占用的内存过多了,影响正常运行程序需要的内存,那么会释放掉一部分cache内存,但是总量会保持一个很高的值,所以,linux总是能最大限度的使用内存,就算加到16G,32G内存,也会随着不断的IO操作,内存的free值会慢慢减少到只有几M,想要内存不发生这种情况,只有一个办法:把内存加到比硬盘大。

解决办法:

手动释放cache的办法:

# free
             total       used       free     shared    buffers     cached
Mem:        247400     123756     123644      33240       7728      63296
-/+ buffers/cache:      52732     194668
Swap:            0          0          0
# echo 3 >  /proc/sys/vm/drop_caches 
# free
             total       used       free     shared    buffers     cached
Mem:        247400      99744     147656      33240        288      47132
-/+ buffers/cache:      52324     195076
Swap:            0          0          0
# 

使用echo 3 >  /proc/sys/vm/drop_caches可以看到buffers和cache占用的内存明显减小;

当然,这个文件可以设置的值分别为1、2、3。它们所表示的含义为:

echo 1 > /proc/sys/vm/drop_caches:表示清除pagecache。
echo 2 > /proc/sys/vm/drop_caches:表示清除回收slab分配器中的对象(包括目录项缓存和inode缓存)。slab分配器是内核中管理内存的一种机制,其中很多缓存数据实现都是用的pagecache。
echo 3 > /proc/sys/vm/drop_caches:表示清除pagecache和slab分配器中的缓存对象。

        Linux内核会在内存将要耗尽的时候,触发内存回收的工作,以便释放出内存给急需内存的进程使用。一般情况下,这个操作中主要的内存释放都来自于对buffer/cache的释放。尤其是被使用更多的cache空间。既然它主要用来做缓存,只是在内存够用的时候加快进程对文件的读写速度,那么在内存压力较大的情况下,当然有必要清空释放cache,作为free空间分给相关进程使用。所以一般情况下,我们认为buffer/cache空间可以被释放,这个理解是正确的。

        但是这种清缓存的工作也并不是没有成本。理解cache是干什么的就可以明白清缓存必须保证cache中的数据跟对应文件中的数据一致,才能对cache进行释放。所以伴随着cache清除的行为的,一般都是系统IO飙高。因为内核要对比cache中的数据和对应硬盘文件上的数据是否一致,如果不一致需要写回,之后才能回收。

# cat /proc/meminfo
MemTotal:         247400 kB
MemFree:          147436 kB
MemAvailable:     158788 kB
Buffers:             440 kB
Cached:            47156 kB
SwapCached:            0 kB
Active:            33752 kB
Inactive:          41008 kB
Active(anon):      31000 kB
Inactive(anon):    29408 kB
Active(file):       2752 kB
Inactive(file):    11600 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 4 kB
Writeback:             0 kB
AnonPages:         27212 kB
Mapped:            22920 kB
Shmem:             33252 kB
Slab:              14684 kB
SReclaimable:       4700 kB
SUnreclaim:         9984 kB
KernelStack:        2880 kB
PageTables:         1232 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:      123700 kB
Committed_AS:     502804 kB
VmallocTotal:   258867136 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB

        使用cat /proc/meminfo命令我们可以看到MemFree和MemAvailable的容量是不一样的,说linux系统可使用内存不够是系统会立即去释放cache的内存,已维持系统进程正常运行,只有当cache内存也不足时,(即MemAvailable非常小的时候)系统才会kill掉部分进程。

猜你喜欢

转载自blog.csdn.net/yufeng1108/article/details/123892792