- A+
遇到了好多次有人反映说我系统内存不够用了,然后就给我top的total结果,其实这样不足于说明内存不够用了,其实,在Linux系统上查看内存使用状况最常用的命令是free,其中buffers和cache通常被认为是可以回收的,free执行命令结果如下:
当内存紧张的时候,有一个常用的手段就是使用下面的命令来手工回收cache:
echo "3"> /proc/sys/vm/drop_caches
注:drop_caches接受以下三种值:
- To free pagecache:
echo 1 > /proc/sys/vm/drop_caches - To free reclaimable slab objects (includes dentries and inodes):
echo 2 > /proc/sys/vm/drop_caches - To free slab objects and pagecache:
echo 3 > /proc/sys/vm/drop_caches
当我们考虑有多少cache可供回收的时候,首先要知道的是:不同版本的”free”命令计算cache值的算法不同,据不完全统计举例如下:
- 版本:procps-3.2.8-36
cache值等于/proc/meminfo中的”Cached”; - 版本:procps-3.3.9-10.1
cache值等于/proc/meminfo的 [Cached + SReclaimable]; - 版本:procps-ng-3.3.10-3
cache值等于/proc/meminfo的 [Cached + Slab]。
注:
/proc/meminfo中的”Cached”表示page cache所占用的内存大小;
“Slab”表示内核Slab所占用的内存大小,slab有的可回收有的不可回收,其中可回收的通过”SReclaimable”表示,不可回收的通过”SUnreclaim”表示。
所以,对上述第2、3版本的”free”命令,”echo 1 > /proc/sys/vm/drop_caches”对其中的SReclaimable或Slab部分是不起作用的。
即便仅考虑page cache (对应于 /proc/meminfo 的”Cached”),也并不是所有的页面都可以回收的:
首先,drop_caches只回收clean pages,不回收dirty pages,参见https://www.kernel.org/doc/Documentation/sysctl/vm.txt
所以如果想回收更多的cache,应该在drop_caches之前先执行”sync”命令,把dirty pages变成clean pages。
其次,即使提前执行了sync命令,drop_cache操作也不可能把cache值降到0,甚至有时候cache值几乎没有下降,这是为什么呢?因为page cache中包含的tmpfs和共享内存是不能通过drop_caches回收的。
Page cache用于缓存文件里的数据,不仅包括普通的磁盘文件,还包括了tmpfs文件,tmpfs文件系统是将一部分内存空间模拟成文件系统,由于背后并没有对应着磁盘,无法进行paging(换页),只能进行swapping(交换),在执行drop_cache操作的时候tmpfs对应的page cache并不会回收。
我们通过实验来观察tmpfs文件对free命令的影响:
结论:
tmpfs占用的page cache是不能通过drop_caches操作回收的,tmpfs占用的page cache同时也算进了”shared”中,也就是说,被视为共享内存。
Linux kernel利用tmpfs实现共享内存(shared memory),参见:
https://www.kernel.org/doc/Documentation/filesystems/tmpfs.txt所以共享内存也和tmpfs一样,属于page cache,但又不能被drop_caches回收。这里所说的共享内存包括:
- SysV shared memory
是通过shmget申请的共享内存,用”ipcs -m”或”cat /proc/sysvipc/shm”查看; - POSIX shared memory
是通过shm_open申请的共享内存,用”ls /dev/shm”查看; - shared anonymous mmap
通过mmap(…MAP_ANONYMOUS|MAP_SHARED…)申请的内存,可以用”pmap -x”或者”cat /proc/<PID>/maps”查看;
注:mmap调用参数如果不是MAP_ANONYMOUS|MAP_SHARED,则不属于tmpfs,比如MAP_ANONYMOUS|MAP_PRIVATE根本不属于page cache而是属于AnonPages,MAP_SHARED属于普通文件,对应的page cache可以回写硬盘并回收。
我们通过一个实验来观察共享内存对free命令的影响。以下程序通过shared anonymous mmap方式申请256MB大小的内存:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAP_SIZE 268435456
int main()
{
char *addr;
ssize_t s;
addr = mmap(NULL, MAP_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, -1, 0);
if (addr == MAP_FAILED) {
fprintf(stderr, "mmap failed\n");
exit(EXIT_FAILURE);
}
memset(addr, 9, MAP_SIZE);
printf("mmap done, memset done, check free output. Press any key to exit...\n");
getchar();
exit(EXIT_SUCCESS);
}
实验过程如下:
结论:cache值包含了共享内存的大小,然而drop_caches是不能回收它的。
注:上例是shared anonymous mmap,如果是SysV shared memory或IPC shared memory,结果是一样的。
总结:为什么drop_caches操作不能回收所有的page cache?因为
- dirty pages不能回收;
- 共享内存和tmpfs不能回收(注意观察free命令显示的shared值);
- 不同版本的free命令有不同的计算cache值的方法,有的包含了slab或SReclaimable,”echo 1 > /proc/sys/vm/drop_caches”是不能回收slab的,”echo 3 > /proc/sys/vm/drop_caches”也只是回收slab中的SReclaimable部分。
- 安卓客户端下载
- 微信扫一扫
- 微信公众号
- 微信公众号扫一扫