1、现象
板子Mem: 128MB,Flash: 32MB。
板子启动后,默认配置下,剩余的内存约90M,当开启一个wget任务后,下载的是网易开源镜像文件,下载速度约900KB/S,这时板子的内存以每秒几M或十几M的速度消耗,很快就只剩下约2M的内存。而且有时候,会出现内存耗尽而导致死机的问题。
2、定位与分析
1)wget自身对内存的分配和使用。wget通过socket来将服务器数据读取到磁盘文件,每下载一个
文件只打开、关闭一次磁盘文件,每次往磁盘文件写16k数据,16k是一个静态字符数组。由此可知,wget自身不会申请过多的内存,所以就不会有内存申请过多而没有释放的问题。
2)修改内核对cache的处理机制。主要修改Proc/sys/vm下的文件的值。
vm.dirty_ratio =1 该文件表示如果进程产生的脏数据到达系统整体内存的百分比,此时进程自行把脏数据写回磁盘。
vm.dirty_background_ratio=1 该文件表示脏数据到达系统整体内存的百分比,此时触发pdflush进程把脏数据写回磁盘。
vm.dirty_writeback_centisecs=2 该文件表示pdflush进程周期性间隔多久把脏数据写回磁盘。
vm.dirty_expire_centisecs=3 这个参数声明Linux内核写缓冲区里面的数据多“旧”了之后,pdflush进程就开始考虑写到磁盘中去。
vm.swappiness=100 该文件表示系统进行交换行为的程度,数值(0-100)越高,越可能发生磁盘交换。
vm.vfs_cache_pressure=163 该文件表示内核回收用于directory和inode cache内存的倾向
vm.overcommit_memory=2 该文件指定了内核针对内存分配的策略,其值可以是0、1、2
vm.lowmem_reserve_ratio=3232 8
对上面列出的文件的修改是没有起到作用的,只是可以稍为降低损耗内存的速度。在proc/sys/vm下的文件中,有两个文件的值是起到作用的,即文件min_free_kbytes和drop_caches。
min_free_kbytes:该文件表示强制Linux VM最低保留多少空闲内存(Kbytes)。在BCM 11AC中将此值设为8192(即8M),内存就会维持在约10M以上。
drop_caches的详细文档如下:
Writing to this will cause the kernel to drop clean caches, dentries and inodesfrom memory, causing that memory to become free.
To free pagecache:
* echo 1 > /proc/sys/vm/drop_caches
To free dentries and inodes:
* echo 2 > /proc/sys/vm/drop_caches
To free pagecache, dentries and inodes:
* echo 3 > /proc/sys/vm/drop_caches
As this is a non-destructive operation, and dirty objects arenotfreeable, the user should run "sync" first in order to make sureallcached objects are freed.
This tunable was added in 2.6.16.
通过周期地调用“echo 3> /proc/sys/vm/drop_caches”就可以定时释放内存。
1)函数。这里尝试的函数主要是用来释放cache或设置cache的大小的。用过的函数有sync、fsync、fdatasync、setvbuf,而fsync,fstat,
posix_fadvise一组函数在虚拟机系统上跑是有效果的,可以避免内存的增加,但板子的系统没有取得效果,内存依然会被耗掉。至此可以基本可以肯定板子的文件系统对cache导致了cache没有及时回收的问题。
2)缓存测试。判断是不是cache没有释放而引起内存耗用过大:在文件下载完成后,2~3s拔
下U盘,发现U盘文件已经损坏,基本可断定是cache引起的原因
3)直接对U盘进行文件的读写,比如直接将U盘中的文件A,复制到U盘的文件B,发现内存会马上耗掉,
至此可以肯定是文件系统对cache处理机制的问题。
3 处理
通过2的定位分析过程,知道是文件系统导致了缓存无法及时释放,在不修改现有文件系统情况下,现在可以有两种处理方法。
1)修改min_free_kbytes,将min_free_kbytes的值设置为8192,即8M。
2)周期调用“echo 3 > /proc/sys/vm/drop_caches”就可以定时释放内存
以上两种方法也存在不足,即无法应对突发的缓存增长,比如三个任务同时下载,同时向系统申请的内存之和已经超过系统可用内存,这里依然会内存耗尽而死机。