buffers/cache
free命令
Linux下的free
命令是显示当前内存的使用,-m
代表用MB字节显示,-g
代表用GB字节显示:
# free -m
total used free shared buffers cached
Mem: 48258 48008 250 0 30 33333
-/+ buffers/cache: 14643 33614
Swap: 24199 6245 17954
# free -g
total used free shared buffers cached
Mem: 47 46 0 0 0 32
-/+ buffers/cache: 14 32
Swap: 23 6 17
参数详解
第一部分Mem行:
- total: 内存总数: 48258MB -> 47G
- used: 已经使用的内存数: 48008 -> 46G
- free: 空闲的内存数: 250MB -> 0G
- shared: 当前已经废弃不用,总是0: 0MB -> 0G
- buffers: 缓存内存数: 30MB -> 0G
- cached: 缓存内存数: 33333MB -> 32G
可以看到free(空闲的内存数)的内存数只有250MB,内存大部分被buffers/cache使用了,这只是对 操作系统 层面来说的。在Linux系统中有这么一种思想,内存不用白不用,因此它尽可能的cache和buffer一些数据,以便于提高IO性能。但实际上这些内存应用程序还是可以立刻拿来使用的。
第二部分(-/+ buffers/cache)行:
在Linux系统中,为了提高文件系统性能,内核利用一部分物理内存分配出缓存,用于缓存系统读写过的数据文件,这样可以提高IO性能。
上面的 -/+ buffers/cache 可以分为: -buffers/cache、+buffers/cache
- -buffers/cache: used内存数: 14643MB -> 14G
- +buffers/cache: free内存数: 33614MB -> 32G
可见-buffers/cache 反映的是被程序实实在在吃掉的内存总数(14G),而 +buffers/cache: 反映的是可以使用的内存总数(32G)。
也就是对操作系统来说: buffers/cache 都是被使用的,所以它认为 free 都只有250MB。但是对 应用程序 来说: free 和 buffers/cache 是可以使用的,如果调用内存分配函数(malloc
、new
),这部分内存还是可以分配的。
测试程序
1 |
|
上面的程序很简单,每次申请 1024 * 1024(1M) 的内存,申请 16 * 1024次, 也就是总共申请了 16G 的内存。在每次申请完内存后调用memset
函数, 注意 ,如果在申请完内存后。如果不使用这块内存的话,系统是不会给你的程序分配内存的,也就是说只有你真正使用到了这块内存,系统才会为你的程序分配,这就是上面为什么要使用memset
函数的原因。
编译程序:
gcc test.c
查看程序运行前的内存使用情况,并运行程序:
# free -g
total used free shared buffers cached
Mem: 47 46 0 0 0 32
-/+ buffers/cache: 14 32
Swap: 23 6 17
#
# ./a.out
输出结果:
malloc successful
malloc successful
malloc successful
malloc successful
malloc successful
malloc successful
malloc successful
malloc successful
malloc successful
malloc successful
malloc successful
malloc successful
waiting stop......
使用free查看内存的使用情况:
# free -g
total used free shared buffers cached
Mem: 47 46 0 0 0 16
-/+ buffers/cache: 30 16
Swap: 23 6 17
可以看到在上面 free 只有 0G 的情况下,程序依然可以申请成功(16G内存), cached 由原先的 32g 减少到了 16G 。 也就是上面所说的,cached 对应用程序来说,是可以真实使用内存的。
终止程序,查看内存的使用情况:
# free -g
total used free shared buffers cached
Mem: 47 30 16 0 0 16
-/+ buffers/cache: 14 32
Swap: 23 6 17
可以看到在上面 free 变成了 16G, 由此可见,cached的内存是可以被程序使用的。
什么时候会增加cached的使用量?
上面说了,cached 主用于缓存系统读写过的数据文件。下面写个程序,在测试一下:
1 |
|
程序很简单,最后的结果就是创建一个 16G 的out.bin
文件。
运行程序前,查看内存使用的情况,程序运行结束后,创建了一个16G的文件:
# free -g
total used free shared buffers cached
Mem: 47 30 16 0 0 16
-/+ buffers/cache: 14 32
Swap: 23 6 17
#
# ./a.out
#
# ll out.bin -h
-rw-r--r-- 1 root root 16G Apr 27 17:10 out.bin
程序运行结束后,使用free查看内存的使用情况:
# free -g
total used free shared buffers cached
Mem: 47 46 0 0 0 32
-/+ buffers/cache: 14 32
Swap: 23 6 17
#
可以看到 free 由原先的 16G 变为了 0G, cached 从原先的 16G 增加到了 32G。 由此可见,在读写文件的时候,内核使用内存作为缓存,这就导致了cached的增加,但是这部分内存,对于应用程序来说还是可以使用的。
清除cached
cached 也是可以手动清除的,但是伴随着 cached 的清除, 会使系统的IO飚高、系统的性能会急剧下降。
下面这个文件可以用来清除 cached:
# cat /proc/sys/vm/drop_caches
0
使用下面的操作:
echo 1 > /proc/sys/vm/drop_caches
- echo 1 > /proc/sys/vm/drop_caches: 表示清除pagecache。
- echo 2 > /proc/sys/vm/drop_caches: 表示清除回收slab分配器中的对象(包括目录项缓存和inode缓存)。slab分配器是内核管理内存的一种机制。
- echo 3 > /proc/sys/vm/drop_caches: 表示清除pagecache和slab分配器中的对象。
清除cached:
# echo 3 > /proc/sys/vm/drop_caches
# cat /proc/sys/vm/drop_caches
3
# free -g
total used free shared buffers cached
Mem: 47 18 29 0 0 4
-/+ buffers/cache: 13 33
Swap: 23 6 17
cached 从原先的 32G 减少到了 4G, free 增加到了 29G。
为什么cached没有被完全清除呢? 有哪些cached是不可以被回收呢?
tmpfs
Linux提供了一种文件系统叫做 tmpfs, 它可以将内存的一部分空间拿来当做文件系统使用,使内存空间可以当做文件来用。手工创建一个 tmpfs 。
# mkdir /tmp/tmpfs
# mount -t tmpfs -o size=16G none /tmp/tmpfs
# df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/mapper/VolGroup-lv_root
51606140 48358024 626676 99% /
tmpfs 24708300 1729180 22979120 7% /dev/shm
/dev/sda1 495844 38259 431985 9% /boot
/dev/mapper/VolGroup-lv_home
1045411708 696662912 295644976 71% /home
/home/iso/rhel-server-6.4-x86_64-dvd.iso
3632776 3632776 0 100% /mnt/redhat-iso
none 16777216 0 16777216 0% /tmp/tmpfs
上面创建了一个新的 tmpfs,它的空间是 16G。 现在可以在/tmp/tmpfs
中创建一个 16G 以内的文件,看它占用的是哪部分内存?
# free -g
total used free shared buffers cached
Mem: 47 19 28 0 0 5
-/+ buffers/cache: 13 33
Swap: 23 6 17
#
#
# dd if=/dev/zero of=/tmp/tmpfs/testfile bs=1G count=16
16+0 records in
16+0 records out
17179869184 bytes (17 GB) copied, 19.5241 s, 880 MB/s
#
# free -g
total used free shared buffers cached
Mem: 47 35 12 0 0 21
-/+ buffers/cache: 13 33
Swap: 23 6 17
在tmpfs
目录下创建了一个 16G 的文件,并通过前后的free
命令的对比发现,cached 增长了 16G。 现在收到清除 cached:
# echo 3 > /proc/sys/vm/drop_caches
# free -g
total used free shared buffers cached
Mem: 47 35 12 0 0 21
-/+ buffers/cache: 13 33
Swap: 23 6 17
可以看到, cached 占用的空间并没有被释放,其中 16G 的空间仍然被/tmp/tmpfs
中的文件占用。那么tmpfs
占用的空间什么时候会被释放呢?是在文件被删除的时候,如果不删除文件,无论内存耗尽到什么程度,内核都不会自动帮你把tmpfs
中文件删除,来释放 cached 的空间。
# rm -rf /tmp/tmpfs/testfile
# free -g
total used free shared buffers cached
Mem: 47 19 28 0 0 5
-/+ buffers/cache: 13 33
Swap: 23 6 17
这是cached第一种不能被回收的情况。
共享内存
共享内存是系统提供一种常用的进程间通信(IPC)方式。
1 |
|
程序功能很简单,就是申请了一段 2G 共享内存,然后退出程序,但是在退出之前并没有删除这段共享内存。
# free -g
total used free shared buffers cached
Mem: 47 17 29 0 0 3
-/+ buffers/cache: 13 33
Swap: 23 6 17
#
# ./a.out
# free -g
total used free shared buffers cached
Mem: 47 19 27 0 0 5
-/+ buffers/cache: 13 33
Swap: 23 6 17
cached 空间由 3G 增加到了 5G。那么这段 cached 能被回收吗?
# echo 3 > /proc/sys/vm/drop_caches
# free -g
total used free shared buffers cached
Mem: 47 19 27 0 0 5
-/+ buffers/cache: 13 33
Swap: 23 6 17
结果是仍然不可回收。这段共享内存即使没人使用,仍然会长期存放在 cached, 直到其被删除。
# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x73005aaa 5111808 root 644 4961048 0
0x73005aab 5144577 root 644 6328 0
0x0063a001 11304962 root 666 84399200 4
0x0064a001 20873219 root 666 986174560 19
0x0063a002 11337732 root 666 84399200 3
0x0063a003 11370501 root 666 84399200 6
0x0063a008 11403270 root 666 10998880 2
0x0063a009 11436039 root 666 1561696 2
0x0063a004 11468808 root 666 42456160 4
0x0063a005 11501577 root 666 21484640 3
0x0063a007 11534346 root 666 42456160 4
0x0063a006 11567115 root 666 84399200 4
0x0064a002 20905996 root 666 52941920 18
0x7b5189bc 1277965 oracle 660 1612709888 348
0x01020002 491534 root 600 2048000000 1
0x73020064 19922959 root 644 4961048 1
0x73020063 19955728 root 644 6328 1
0x00112234 20938769 root 666 2147483648 0
#
#
# ipcrm -m 20938769
#
# free -g
total used free shared buffers cached
Mem: 47 17 29 0 0 3
-/+ buffers/cache: 13 33
Swap: 23 6 17
删除共享内存后,cached 被正常释放了。
总结
- 在Linux系统中,内存是用来用的,不是用来看的。free空间变少,cached 占用很高,并不代表程序的可用内存减少,cached 中的大部分内存,是可以给应用程序
malloc
使用。只有tmpfs
、共享内存才会真正占用 cached 的内存空间。 tmpfs
中存储的文件会占用 cached,除非文件删除,否则这个 cached 不会自动释放。- 共享内存会占用 cached 空间,除非共享内存被删除,否则这个 cached 不会自动释放。
- cached 可以手动清除,但是清除后会影响IO,导致系统性能下降。
swap
swap
分区主要是当物理内存不足时,可以将一部分内存页进行swap
操作,swap
分区由硬盘提供。但是对于需要高并发、高吞吐的应用来说,磁盘IO通常会成为系统瓶颈。 在Linux中,并不是要等到所有物理内存都使用完才会使用到swap ,系统参数swppiness
会决定操作系统使swap
的倾向程度。swappiness
的取值范围是0~100,swappiness
的值越大,说明操作系统可能使用swap
的概率越高,swappiness
值越低,表示操作系统更加倾向于使用物理内存。swap
的默认值是60。
swappines
的重要值:
- 0: 在
Linux3.5
以及以上:宁愿用OOM killer
也不用swap
。在Linux3.4
以及更早:宁愿用swap
也不用OOM killer
。 - 1: 在
Linux3.5
以及以上:宁愿用swap
也不用OOM killer
。 - 60: 默认值
- 100: 操作系统会主动会用
swap
。
OOM(Out Of Memory)killer
机制是指Linux
操作系统发现可用内存不足时,强制杀死一些用户进程(非内核进程),来保证系统有足够的可用内存进行分配。
设置方法
echo {bestvalue} > /proc/sys/vm/swappiness
但是上述方法在系统重启后就会失效,为了让配置在重启Linux
操作系统后立即生效,只需要在/etc/sysctl.conf
追加vm.swappiness={bestvalue}
即
可。
echo vm.swappiness={bestvalue} >> /etc/sysctl.conf
查看swap的总体情况
Linux
提供了free
命令来查询操作系统的内存使用情况,其中也包含了swap
的相关使用情况。
最后一行的swap
统计,从执行结果看,swap
一共有2044MB,使用了0MB,空闲2044MB。
$ free -m
total used free shared buffers cached
Mem: 1983 989 994 8 70 374
-/+ buffers/cache: 544 1438
Swap: 2044 0 2044
实时查看swap的使用
Linux
提供了vmstat
命令查询系统的相关性能指标,其中包含负载、CPU、内存、swap、IO的相关属性。但其中和swap
有关的指标是si和so,它们分别代表操作系统的swap in
和swap out
。下面是执行vmstat
(每隔一秒输出)的效果,可以看到si
和so
都为0,代表当前没有使用swap
。
$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 975644 72376 394948 0 0 1596 34 134 862 7 4 88 0 0
0 0 0 975684 72376 394948 0 0 0 0 129 388 4 0 96 0 0
0 0 0 975684 72376 394948 0 0 0 0 152 644 6 1 93 0 0
0 0 0 975684 72376 394948 0 0 0 0 107 428 8 1 91 0 0
0 0 0 975684 72376 394948 0 0 0 0 128 701 10 1 89 0 0
0 0 0 975684 72376 394948 0 0 0 0 334 719 9 1 89 0 0
0 0 0 975684 72376 394948 0 0 0 0 312 582 4 3 93 0 0
0 0 0 975684 72376 394948 0 0 0 0 225 437 5 1 94 0 0
查看指定进程的swap使用情况
Linux
操作系统中,/proc/{pid}
目录是存储指定进程的相关信息,其中/proc/{pid}/smaps
记录了当前进程所对应的内存映像信息,可以查询到指定进程的swap
使用情况。
$ cat /proc/2941/smaps | grep -i Swap
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
Swap: 0 kB
其中Swap
字段代表该内存块存在swap
分区的数据大小。通过执行如下命令,就可以找到每个内存块镜像信息中,这个进程使用到的swap
量,通过求和就可以算出总的swap
用量。
测试程序
1 |
|
这个程序的功能,主要是每次申请 1M 的内存,总共申请 16G, 但是系统可以使用的内存如下: free(994M)、cached(374M),加起来才1G。
$ free -m
total used free shared buffers cached
Mem: 1983 989 994 8 70 374
-/+ buffers/cache: 544 1438
Swap: 2044 0 2044
编译运行程序,使用vmstat实时的观察swap分区,可以看到si、so不断的在增大:
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 316892 1538192 19744 139748 8 0 8 0 143 1456 8 3 89 0 0
2 0 316892 1538192 19744 139748 0 0 0 0 116 897 8 3 89 0 0
1 0 316884 1538192 19752 139744 4 0 4 64 94 502 4 1 94 1 0
1 0 316876 1208056 19876 139748 12 0 148 0 174 2956 11 19 69 1 0
1 0 316868 78116 19876 139752 20 0 20 0 497 9447 38 62 0 0 0
2 11 654592 13336 88 6960 1604 1385944 50956 1386080 2228 9403 12 84 0 3 0
3 1 1897088 13676 336 29392 9960 206812 58616 206828 5346 13090 6 86 0 8 0
3 1 2075384 13584 84 12292 212 176516 7752 176516 2853 4154 16 84 0 0 0
0 0 331536 1693028 640 29544 1036 17968 39140 18024 948 2009 4 36 41 1
在swap分区使用完后,程序会被Killed:
malloc: 3355 MB
malloc: 3356 MB
malloc: 3357 MB
malloc: 3358 MB
malloc: 3359 MB
malloc: 3360 MB
malloc: 3361 MB
malloc: 3362 MB
malloc: 3363 MB
Killed
总结
swap
分区主要是当物理内存不足时,Linux系统可以把部分inactive
的内存页置换到swap
分区。但是,并不是要等到所有物理内存都使用完才会使用到swap
。这取决于内核的LRU
调度算法。如果用free
命令,看到swap
有被使用,可以使用vmstat
实时的查看swap
,也可以查看指定的进程的是否有用到swap
。