计算linux使用了多少内存
一,系统有多少空闲内存?
关键一点,要在除去LINUX使用的文件系统"Cached"和磁盘buffers后的结果。
什么是文件系统"cached"和磁盘buffers? 请见free 输出中的cached和buffers。
# free -m
total used free shared buffers cached
Mem: 700 688 12 0 130 381
-/+ buffers/cache: 176 523
Swap: 1961 20 1940
上面这个176实际上是 688-130-381的结果 177 M。(约等于176,因为从k到m做了换算)
验证:
运行清空文件系统"cached"和磁盘buffer的命令
# echo 3 > /proc/sys/vm/drop_caches
就会看到
# free -m
total used free shared buffers cached
Mem: 700 48 651 0 0 8
-/+ buffers/cache: 40 660
Swap: 1961 7 1953
发现used为 40M, buffers为0,cached为8了。不知道为什么8M去不掉,关系不大吧,只有8M。
这个严重建议看一下这篇:http://km.oa.com/group/SA/article_view/57194 其实这段就是抄这一篇的。
如果没有共享内存文章到这里就结束,但问题是还有共享内存。
二,共享内存存放在哪里?
答:SysV Shm存放在cached中
如果查一下内核文档源码啥的,应该也能查出来;不过不会查。这次不讲理论,测试一下,眼见为实。
#1,找一个空的环境,清空文件系统"cached"和磁盘buffers,能看到系统used内存为40M
# echo 3 > /proc/sys/vm/drop_caches
# free -m
total used free shared buffers cached
Mem: 700 48 651 0 0 8
-/+ buffers/cache: 40 660
Swap: 1961 7 1953
#3, domem 是一个测试程序:
申请1G 共享内存,memset 前100M内容为1,sleep 1秒,把它的/proc/pid/smaps中关于共享内存的那一段打印出来
大概的源码是
shmid = shmget(ftok(argv[0], 1), 1024ul *1024*1024*1 , IPC_CREAT|0666);
printf("shmid: %d\n", shmid);
mem = shmat(shmid, NULL, 0);
memset (mem, \'1\', 1024*1024*100*1);
sleep (1);
printf("PID:%d\n", getpid());
sprintf(sysbuf, "grep -A 6 SYSV /proc/%d/smaps", getpid());
system(sysbuf);
# ./domem sysv
# Command: sysv
shmid: 6520836
PID:5720
77de2000-b7de2000 rw-s 00000000 00:07 6520836 /SYSVffffffff (deleted)
Size: 1048576 kB
Rss: 102400 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 102400 kB
#4 看到,现在cached已经上涨到110M了,大约加了100M,不会是巧合吧
# free -m
total used free shared buffers cached
Mem: 700 150 549 0 0 110
-/+ buffers/cache: 39 660
Swap: 1961 7 1953
#5,清掉缓存,看到cached还有109M,清不掉了,还真是和刚才的100M SHM有关系
# echo 3 > /proc/sys/vm/drop_caches
# free -m
total used free shared buffers cached
Mem: 700 149 551 0 0 109
-/+ buffers/cache: 39 660
Swap: 1961 7 1953
#6,杀掉domem进程,再清io缓存,还是清不掉
# killall -9 domem
[1]+ Killed ./domem sysv
# free -m
total used free shared buffers cached
Mem: 700 150 549 0 0 111
-/+ buffers/cache: 39 660
Swap: 1961 7 1953
# echo 3 > /proc/sys/vm/drop_caches
# free -m
total used free shared buffers cached
Mem: 700 148 551 0 0 109
-/+ buffers/cache: 39 661
Swap: 1961 7 1953
#7 删除共享内存,再看,cached的值下来了,减少了约100M
# ipcrm -m 6029316
# free -m
total used free shared buffers cached
Mem: 700 50 650 0 0 10
-/+ buffers/cache: 38 661
Swap: 1961 7 1953
#8 试一下posix shm,发现posix shm也是放在cached memory中的。
domem也支持posix shm的,大家有兴趣试一下,我就不写了。
./domem posix posixfile 10
Domem.c在本文最后有下载连接。
三,共享内存的申请大小和已分配大小?
在smaps文件中,有一些带有/SYSV开头的文件,就是共享内存了;当然,rw-s标志中的s才是关键。在下面这段中:
77de2000-b7de2000 rw-s 00000000 00:07 6520836 /SYSVffffffff (deleted)
Size: 1048576 kB
Rss: 102400 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 102400 kB
看到:Size是它申请的共享内存的大小,Rss是已分配到物理内存的量。
再跑一个./domem sysv
# PID:5833
77e11000-b7e11000 rw-s 00000000 00:07 6520836 /SYSVffffffff (deleted)
Size: 1048576 kB
Rss: 102400 kB
Shared_Clean: 0 kB
Shared_Dirty: 102400 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
看到:Rss没有变,但Private_Dirty变为0了,而Shared_Dirty变为100M了。
还看到:
内核会建一个临时文件/SYSVffffffff (deleted) ,以它的inode为shmid。
这里隐约能感觉到:共享内存和文件是相对应的,被内核算到cached还是比较合适。
在上面例子中, 6520836 是shmid,本来它应该是/SYSVffffffff的inode的。
四:计算 linux使用内存 的公式是?
free中去除cached/buffers后的used + 已使用共享内存的Rss总和。
如果不那么精确,只查申请的SHM的SIZE,又是Sysv SHM的话,可以用下面这串命令算,
# ipcs -m | awk \'{s+=$5} END {print s/1024/1024, "M"}\'
1026.76 M
如果是posix shm的话,那可能还得去遍历所有的smaps文件,grep一下第2个字段的最后一个字符为s(SHARE)的行,查一下它的Size。
或者,光查ipcs的Size都可能是不靠谱的,天知道开发同事们是怎么定义这个Size的;
光查Rss也不对,万一系统跑着跑着就把申请的内存用光了。所以说运维要和研发同事多沟通。
五,公司tnm网管系统上哪个内存性能指标是准确的?
用TNM系统查数据的同学看一下吧,不用的就忽略, 下面这个表是agent关于内存项采集的说明。
|
应用程序使用内存 |
agent读取/proc/meminfo文件,(MemTotal – MemFree – Buffers – Cached)/1024得到应用程序使用内存数。 |
|
MEM使用量 |
agent读取/proc/meminfo文件,MemTotal – MemFree得到MEM使用量。 |
|
Private内存 |
通过/proc/<进程ID>/smaps文件计算出所有进程的private内存总和。 |
|
Virtual内存 |
通过/proc/<进程ID>/samps计算出所有进程的virtual内存总和。 |
|
Private+IPCS |
所有进程的private内存+ipcs内存的总和。 |
MEM使用量:WINDOWS的有意义,LINUX的意义不大
应用程序使用内存数:没有共享内存的情况下,最准确
private内存使用:每个shmid只有1个进程使用时,最准确
private内存加共享内存占用:每个shmid 有2个进程使用时,最准确
virtual内存使用:不懂
注意:网管agent采集内存量的时候,去遍历smaps文件取private_dirty/private_clean累加;
而使用linuxthread的程序,每一个线程都会有一个进程号,导致采集结果为线程数量倍数这么大。
不少老的mysqld就是使用这种线程库的。
六,SWAP?
想知道SWAP量多少时,我们可以接受?
想了很久没有想清楚。
mysqld由于oom killer被杀掉,就没有充分考虑sysv shm的情况!另外,文件系统的cache和磁盘的buffer,我之前就以为只有一个文件系统的cache!