追踪linux命令Free
---宫博(杨祥合) 2014-04-25
1.free命令
Mem:这一行,按OS角度理解内存使用情况.
有等式:1954 = 1120 + 834 其中,OS层的buffers和cached分别为85M和614M
-/+ buffers/cache:这一行,从应用程序角度看待内存使用情况
有等式:
420 = 1120 - (85 + 614)
1534 = 834 + (85 + 614)
Note:值有时差1,是由于四舍五入的近似值
总结公式:
对Mem这一行来看:
OS层来看: Mem: total = used + free,
其中used内存中,包含了buffers和cached的内存,所以, buffers + cached < used
从-/+ buffers/cache:这一行(应用程序的角度)看:
buffer/cached_used = mem_used - (mem_buffers + mem_cached)
buffer/cached_free = mem_free + (mem_buffers + mem_cached)
容易理解吧?
诠释一下,
应用程序已经使用的内存= OS层使用的内存- ( OS层buffer + OS层的cache )
应用程序感知到的空闲内存= OS层使用的内存+ ( OS层buffer + OS层的cache )
问题来临:
OS层的cache什么时候用到?
buffer和cache有什么分别?
cache的效果如何?
2.buffer && cache
(1)buffer && cache:
看老外怎么说
(1)A buffer is something that has yet to be "written" to disk.
(2)A cache is something that has been "read" from the disk and stored for later use.
Note:
Linux内核对cache和buffer,对OB来说,若有内存需要,是可以快速释放的。所以,在运维管理中,OS层面看到的cache的值是可以减少的,只要面临压力,内核会主动回收。
(2)清空cache
(办法1:命令行方法)
Emptying the buffers cache
If you ever want to empty it you can use this chain of commands.
$ free && sync && echo 3 > /proc/sys/vm/drop_caches && free
total used free shared buffers cached
Mem: 1018916 980832 38084 0 46924 355764
-/+ buffers/cache: 578144 440772
Swap: 2064376 128 2064248
total used free shared buffers cached
Mem: 1018916 685008 333908 0 224 108252
-/+ buffers/cache: 576532 442384
Swap: 2064376 128 2064248
You can signal the Linux Kernel to drop various aspects of cached items by changing the numeric argument to the above command.
NOTE: clean up memory of unnecessary things (Kernerl 2.6.16 or newer). Always make sure to run sync first to flush useful things out to disk!!!
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
The above are meant to be run as root. If you're trying to do them using sudo then you'll need to change the syntax slightly to something like these:
$ sudo sh -c 'echo 1 >/proc/sys/vm/drop_caches'
$ sudo sh -c 'echo 2 >/proc/sys/vm/drop_caches'
$ sudo sh -c 'echo 3 >/proc/sys/vm/drop_caches'
Note:上述在操作时,我直接drop掉cache,推荐使用sync将数据刷到盘上。
(办法2,库函数)
```c
int dcache(int fd, int sync_data)
{
off_t off,len;
struct stat buf;
int save_errno;
save_errno = errno;
if (sync_data) {
if (fsync(fd) < 0) {
printf("%s\n",strerror(errno));
errno = save_errno;
return -1;
}
}
if (fstat(fd,&buf) < 0) {
printf("%s\n",strerror(errno));
errno = save_errno;
return -1;
}
off = 0;
len = buf.st_size;
if (posix_fadvise(fd,off,len,POSIX_FADV_DONTNEED) < 0) {
printf("%s\n",strerror(errno));
errno = save_errno;
return -1;
}
return 0;
}
'''
Note:
使用linux系统调用 posix_fadvise
#include <fcntl.h>
int posix_fadvise(int fd, off_t offset, off_t len, int advice);
其中advice,使用选项POSIX_FADV_DONTNEED处理.
3.OS层Cache效果
为了验证cache效果,进行准备工作:
(1)准备一个1G的文件
dd if=/dev/zero of=1G bs=1M count=1024
注意,这里文件名叫做1G,请选用的文件大小,小于物理内存大小.
(2)清空cache:
清除后,cached从1367M降低到243M
(3)结果分析:
读取文件两次,首次读取是通过磁盘IO,读取后,文件基本被缓存在cache中了,
可以看到cache大小刚好增加了1024M.
观察读取时间:第二次读,比第一次少很多.
(4)看看准备好的文件读取程序:(使用这个代码,为了积累经验,与cat这个黑盒子形成一点对比)
```c
#define BUFFSIZE 4096
int
main(void)
{
int n;
char buf[BUFFSIZE];
while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
if (write(STDOUT_FILENO, buf, n) != n)
err_sys("write error");
if (n < 0)
err_sys("read error");
exit(0);
}
'''
(5)用cat来验证,也是可以的,请留意cached的变化
OS层buffer cache的实质: 由双向链表的LRU算法.
4.OB中应用
OB运维管理中,调整比较多的是block_index_cache和block_cache两个内存区域。
在分布式运维中,往往看OS层面的free认为,认为空闲内存,其实不然。
这里看剩余内存,应该采用buffers cache的值,然后参考Mem这一行的free和cached值.
原因,见buffer&&cache中的,第一个Note,这是linux内核的行为.