问题现象:
Linux下从服务器下载文件时,通过回调函数一直写文件,频繁的进行write操作,导致系统可用内存一直减少,有时候可能会导致程序执行因为内存问题异常。
测试代码如下:
/******************************************************************
* Copyright (C) 2019 All rights reserved.
*
* File Name :memory_test.c
* The Author:Wang
* Create Date:2019年08月20日
* Discription:
*
* Update Log :
*
*****************************************************************/
#include#define SIZE (1024 * 1024)
int main (int argc, const char *argv[])
{
int i = 0;
int wrote_byte = 0;
char buffer[SIZE] = {0};
printf("open file : %s\n", argv[1]);
FILE *fp = fopen(argv[1], "ab");
if (NULL == fp) {
printf("open file failed\n");
return -1;
}
for (i = 0; i < SIZE; i++) {
buffer[i] = i;
}
while (1) {
wrote_byte = fwrite(buffer, SIZE, 1, fp);
printf("wrote size : %d\n", SIZE * 1);
if (wrote_byte != 1) {
printf("write failed.\n");
return -1;
}
usleep(500000);
}
fclose(fp);
return 0;
}
运行程序以及通过free命令的现象如下:
不断向文件写数据:
free命令查看系统内存使用情况,free可用的内存一直减少,但是buff/cache部分一直增加:
问题分析:
先看些free命令的参数解释:
total 内存总数
used 已经使用的内存数
free 空闲的内存数
shared 多个进程共享的内存总额
buff/cache Buffer Cache和cached Page Cache 磁盘缓存的大小
available 可用的内存
其中free部分是可用的内存,buff/cache部分是磁盘缓存的大小。关于其中buff/cache的描述 “为了提高磁盘存取效率, Linux做了一些精心的设计, 除了对dentry进行缓存(用于VFS,加速文件路径名到inode的转换), 还采取了两种主要Cache方式:Buffer Cache和Page Cache。前者针对磁盘块的读写,后者针对文件inode的读写。这些Cache有效缩短了 I/O系统调用(比如read,write,getdents)的时间。”,关于这部分的介绍网上有很多的介绍资料,所以上述例子在运行的时候,free的内存一直减少,buff/cache的内存一直增加。
问题解决方法:
一般Linux系统在内存快要消耗完的时候,会触发内存回收的操作,会自动释放一些内存,也就是说会从buff/cache中释放缓存。如果因为这个问题导致程序执行失败的情况,也可以手动进行释放缓存,通过对/proc/sys/vm/drop_caches文件进行操作可以释放缓存。
@ubuntu:$ cat /proc/sys/vm/drop_caches
0
//默认值是0
往上关于这个文件的介绍如下(该部分介绍转自:http://www.idcyunwei.org/post/162.html)
echo 1 > /proc/sys/vm/drop_caches:表示清除pagecache。
echo 2 > /proc/sys/vm/drop_caches:表示清除回收slab分配器中的对象(包括目录项缓存和inode缓存)
echo 3 > /proc/sys/vm/drop_caches:表示清除pagecache和slab分配器中的缓存对象。
所以解决上述例子中问题可以定期执行以下的命令:
sync //落盘处理,保证文件的正确性
echo 3 > /proc/sys/vm/drop_caches //表示清除pagecache和slab分配器中的缓存对象
执行后现象如下图,free部分内存增加了很多,buff/cache部分内存减少了很多: