系统的计算资源主要体现在两个方面,CPU和Memory。了解系统或进程的内存使用情况在工作中是经常需要的。
top
是常用的用来查看系统或进程状态的命令。
top - 06:19:16 up 109 days, 12:26, 83 users, load average: 0.88, 0.68, 0.58 Tasks: 296 total, 1 running, 295 sleeping, 0 stopped, 0 zombie Cpu(s): 3.8% us, 0.2% sy, 0.0% ni, 95.9% id, 0.1% wa, 0.0% hi, 0.0% si Mem: 49454280k total, 33299392k used, 16154888k free, 280616k buffers Swap: 83883388k total, 176672k used, 83706716k free, 21073420k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 16 0 4768 404 372 S 0.0 0.0 0:07.32 init ... ...
free
很适合用来查看系统的可用内存大小。
$ free -m total used free shared buffers cached Mem: 48295 32526 15768 0 274 20586 -/+ buffers/cache: 11666 36629 Swap: 81917 172 81744
这里需要说明的是 “-/+ buffers/cache”行。在一行中,"used"和"free"列分别减去和加上了buffers/cached列的值。
buffers/cached 可能会占用系统内存,但不是必须的。系统在需要时可以收回这部分内存,因而可以算作是空闲(free)内存的一部分。
A buffer is something that has yet to be "written" to disk.
A cache is something that has been "read" from the disk and stored for later use.
缓存(cached)是把读取过的数据保存起来,重新读取时若命中(找到需要的数据)就不要去读硬盘了,若没有命中就读硬盘。其中的数据会根据读取频率进行组织,把最频繁读取的内容放在最容易找到的位置,把不再读的内容不断往后排,直至从中删除。
缓冲(buffers)是根据磁盘的读写设计的,把分散的写操作集中进行,减少磁盘碎片和硬盘的反复寻道,从而提高系统性能。
为了提高性能,操作系统会尽量使用空闲的内存作为buffers或cached。但这些buffers或cached在需要时是可以被其他程序使用的。
一种办法是"Drop Caches",写入一个数字到文件 "/proc/sys/vm/drop_caches".
sync ; # flash cache to disk echo 3 > /proc/sys/vm/drop_caches ; # 清空 cached/buffers
另一种办法是写个程序,消耗内存,直到cached/buffers占用的空间被系统释放。下面的程序引自 Experiments and fun with the Linux disk cache
#include <stdlib.h> #include <stdio.h> #include <string.h> int main(int argc, char** argv) { int max = -1; int mb = 0; char* buffer; if(argc > 1) max = atoi(argv[1]); while((buffer=malloc(1024*1024)) != NULL && mb <= max) { memset(buffer, 0, 1024*1024); printf("Allocated %d MB\n", mb++); } return 0; }
文件 /proc/$pid/status
中包含对应进程的内存使用情况。
$ awk '/^Vm/ {printf "%s %8.1f page\n",$0, $2/4}' /proc/$pid/status VmSize: 54236 kB 13559.0 page # 进程的虚拟内存的大小 VmLck: 0 kB 0.0 page # 加锁的虚拟内存大小 VmRSS: 1972 kB 493.0 page # 使用的物理内存的大小 VmData: 1156 kB 289.0 page # 程序数据段大小 (Heap) VmStk: 212 kB 53.0 page # 栈的大小 (Stack) VmExe: 318 kB 79.5 page # 可执行占用的虚拟内存大小 VmLib: 1342 kB 335.5 page # 动态链接库占用的虚拟内存大小
文件/proc/$pid/statm
从另一个角度反映进程的内存使用情况。
$ cat /proc/20164/statm 13559 493 246 79 0 342 0 # 显示的7个数值单位都是页(page),每页的大小通常是4KB。 # 7个数值分别表示 # 1. VmSize : 进程虚拟内存空间的大小 # 2. VmRSS : 占用的物理内存大小 # 3. VmShared : 共享的页的大小 # 4. VmExe : 程序代码占用的空间大小 # 5. VmLib : 被映像倒任务的虚拟内存空间的库的大小 (不等同于VmLib) # 6. VmData+VmStk : 程序数据段和用户态的栈的大小 # 7. Dirty Pages : 脏页数量
文件/proc/$pid/maps
列出了里程的虚拟内存的映射表。
文件/proc/$pid/smaps
除了包含/proc/$pid/maps
内容之外,还多了些虚拟内存的使用情况数据。
虚拟内存映射表每行有6列:
$ cat /proc/$pid/maps 00400000-00450000 r-xp 00000000 68:01 4948064 /bin/tcsh 0054f000-00554000 rw-p 0004f000 68:01 4948064 /bin/tcsh 00554000-0063f000 rwxp 00554000 00:00 0 2a95556000-2a9556b000 r-xp 00000000 68:01 5079045 /lib64/ld-2.3.4.so $ cat /proc/$pid/smaps 00400000-00450000 r-xp 00000000 68:01 4948064 /bin/tcsh Size: 320 kB Rss: 284 kB Shared_Clean: 284 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 0 kB # 可以根据 smaps文件做汇总计算 $ awk -f mem.awk /proc/$pid/smaps VmSize : 54240 13560 VmRss : 1972 493 Shared : 992 248 Private: 980 245 Dirty : 0 0
上面提到的"mem.awk"文件的内容如下:
/^(Size|Rss|Shared|Private)/ {sum[$1]+=$2} END{ sum_shared = sum["Shared_Clean:"]+sum["Shared_Dirty:"]; sum_private = sum["Private_Clean"]+sum["Private_Dirty:"]; sum_dirty = sum["Shared_Dirty"]+sum["Private_Dirty"]; printf "VmSize : %8d %8d\n", sum["Size:"], sum["Size:"]/4; printf "VmRss : %8d %8d\n", sum["Rss:"], sum["Rss:"]/4; printf "Shared : %8d %8d\n", sum_shared, sum_shared/4; printf "Private: %8d %8d\n", sum_private, sum_private/4; printf "Dirty : %8d %8d\n", sum_Dirty, sum_Dirty/4; }