一、 概述
1. 各种特性的页
l free:空闲页,该页可立即被申请使用
l inactive clean:数据已经被写到磁盘,数据还保留一份在内存,需回收该页。
l Inactive dirty:脏页,页面不可用,页面内容已经被修改但未写入到磁盘,必须将页内容写到磁盘,回收该内存。当磁盘信息比页面里缓存信息更新时,这页就叫脏页,必须回收该内存。
2. 统计进程在使用过程中,有多少页面可申请,有多少页是脏页
l 统计脚本
[root@station9 ~]# vim memory.sh
#!/bin/bash
cat /proc/$1/smaps | awk '
BEGIN { print "Execute before processing input";}
/* process input */
/Shared_Clean/{ CLEAN += $2; }
/Shared_Dirty/{ DIRTY += $2; }
END {
/* execute after processing input */
print "Shared_Clean: " CLEAN;
print "Shared_Dirty: " DIRTY;
}'
l 查询测试
[root@station9 ~]# ./memory.sh 10892
Execute before processing input
Shared_Clean: 664 #可申请的内存
Shared_Dirty: 0 #脏页数
二、 回收dirty pages
1. pdflush进程
pdflush进程负责将内存信息和磁盘信息及时同步,回收脏页,默认至少2个进程。
l [root@station9 ~]# ps -ef|grep pdflush
root 251 19 0 Aug18 ? 00:00:00 [pdflush]
root 252 19 0 Aug18 ? 00:00:00 [pdflush]
2. Tuning pdfulsh
l [root@station9 ~]# sysctl -a |grep vm.nr_pdflush_threads
vm.nr_pdflush_threads = 2
#pdflush进程数,当系统繁忙或内存较小时,适合写大一些,但相对来说会导致下次读取较慢。默认情况,系统会根据磁盘IO的状态,自动调整pdflush数。
l [root@station9 ~]# sysctl -a |grep dirty
vm.dirty_expire_centisecs = 2999
#单位(1%秒)当脏页在内存的时间到达30秒(2999/100)时,pdflush回收脏页。
vm.dirty_writeback_centisecs = 499
#单位(1%秒)默认pdfush每5s(499/100)去监控脏页存活时间。
vm.dirty_ratio = 30
#进程产生的脏页到达整个内存的百分比(30%)时,无需pdflush,进程自行回收脏页。
vm.dirty_background_ratio = 7
#脏页达到整个内存的百分比(7%)时使用,pdflush开始工作,回收脏页。
三、 回收clean pages
1. 提交所有脏页buffer和pages
l sync 强制同步
l echo s > /proc/sysrq-trigger
[root@station9 ~]# ./memory.sh
Execute before processing input
Shared_Clean: 860
Shared_Dirty: 8
[root@station9 ~]# echo "s" > /proc/sysrq-trigger
[root@station9 ~]# ./memory.sh
Execute before processing input
Shared_Clean: 860
Shared_Dirty: 0
2. 回收clean pages
l echo 3 > /proc/sys/vm/drop_caches
[root@station9 ~]# free -m
total used free shared buffers cached
Mem: 4054 600 3453 0 115 325
-/+ buffers/cache: 159 3895
Swap: 8189 0 8189
[root@station9 ~]# echo 3 > /proc/sys/vm/drop_caches
[root@station9 ~]# free -m
total used free shared buffers cached
Mem: 4054 162 3891 0 0 20
-/+ buffers/cache: 141 3913
Swap: 8189 0 8189
四、 Out-of-memory killer(OOM,内存耗尽,自动kill适当进程机制)
1. 需要kill processes的情况
l 所有内存(包括swamp)被用完
l zone_normal内没有可用页
l 页面表内无可用内存
2. 强制保留进程不能被杀死
l 高睡眠进程(该进程消耗内存较少)
l 通过/proc/pid/oom_score参数(可豁免kill的级别)判断
3. 调OOM policy
l 开启oom-kill功能
[root@station9 ~]# sysctl -a|grep oom
vm.panic_on_oom = 0
#0关闭,1开启
l 保护oom-kill级别
echo n >/proc/pid/oom_adj
#-17<=n<=15,值越小进程被杀的可能行就越小
[root@station9 ~]# echo "vm.panic_on_oom = 1" >>/etc/sysctl.conf
[root@station9 ~]# sysctl -p
[root@station9 ~]# echo -17>/proc/10892/oom_adj
[root@station9 ~]# more /proc/10892/oom_adj
-17
[root@station9 ~]# more /proc/10892/oom_score
0
[root@station9 ~]# echo 15 >/proc/10892/oom_adj
[root@station9 ~]# cat /proc/10892/oom_score
1212416
#oom_score值随oom_adj自动变化无需设定,该值越大进程被杀死的机率越大,告诉表示进程被杀死的机率为2的1212416次方。
l 手动模拟oom-kill
[root@memory ~]#echo f > /proc/sysrq-trigger
#模拟oom-kill,通过/var/log/messages显示,不会真正杀死进程,只是模拟效果。
[root@memory ~]#tail -f /etc/log/messages
#查看系统日志,可以显示oom-kill进程。
4. 注意选项
l 杀父进程会同时杀死其子进程
l selinux版本:selinux-policy-targeted-2.4.6-106.el5_1.3 or late
l oom-kill只能解决内存溢出(内存耗完),不能解决内存泄漏(应用程序造成内存无法回收)
五、 Memory leaks(内存泄漏)
1. 两种内存泄漏:
l virtual:应用程序请求时无法使用虚拟地址空间(vsize)
l real:没有可用free内存(rss)
2. 查看系统中内存回收情况
[root@station10 ~]# sar -R 1 120 #每秒查看一次,查看120次
Linux 2.6.18-194.el5 (station10) 2011年08月30日
00时09分44秒 frmpg/s bufpg/s campg/s
00时09分45秒 0.00 0.00 0.00
00时09分46秒 2.00 0.00 0.00
00时09分47秒 0.00 0.00 0.00
00时09分48秒 -252.00 0.00 0.00
00时09分49秒 126.73 1.98 -1.98
#frmpg/s:每秒中系统回收的内存页数(页:4k),负数:内存被占用;正数:内存回收。
#bufpg/s:每秒中系统回收的buffer页数(页:4k),负数:内存被占用;正数:内存回收
#campg/s:每秒中系统回收的cache页数(页:4k),负数:内存被占用;正数:内存回收
3. 观察进程使用内存情况
[root@www ~]# watch -n 1 "ps axo pid,comm,rss,vsize|grep httpd"
Every 1.0s: ps axo pid,comm,rss,vsize|grep httpd Mon Aug 29 17:00:24 2011
10609 httpd 9404 27972
10675 httpd 4496 27972
10676 httpd 4496 27972
10677 httpd 4496 27972
10678 httpd 4496 27972
10679 httpd 4496 27972
10680 httpd 4496 27972
10681 httpd 4496 27972
10682 httpd 4496 27972
#rss:物理内存使用(kb)
#vsize:虚拟内存使用(kb)
4. 查看进程内存泄漏情况
valgrind --tool=memcheck cat /proc/$$/maps
[root@www ~]#ls -ls
[root@www ~]# valgrind --tool=memcheck /proc/$$/maps
......
==10726== LEAK SUMMARY:
==10726== definitely lost: 0 bytes in 0 blocks
==10726== indirectly lost: 0 bytes in 0 blocks
==10726== possibly lost: 0 bytes in 0 blocks
==10726== still reachable: 13,400 bytes in 38 blocks
==10726== suppressed: 0 bytes in 0 blocks
==10726== Rerun with --leak-check=full to see details of leaked memory