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。