取得Linux系统的各种统计信息
本文基于Linux 2.6.x内核
一、取得CPU信息(相关文件/proc/stat)
在一个系统中的/proct/stat文件内容如下
$ cat /proc/stat
cpu 1039426 17799 111249 40729024 65373 8133 0
cpu0 1039426 17799 111249 40729024 65373 8133 0
intr 430346008 419773883 78233 0 5 5 1047009 7 4 1 2 0 5407218 66 0 3776594 262981
ctxt 307543240
btime 1173244314
processes 73837
procs_running 1
procs_blocked 0
其中以“cpu”开头的两行代表系统中有两个CPU核心(我的机子是P4双核的),每一行对应一个CPU核心。后面的数字表示从启动到现在CPU花费在执行各项任务上的时间,单位是USER_HZ(一般是每秒一百次)。
各个数据项从左至右的函义如下:
user:普通进程在用户模下下执行的时间。
nice:被提高优先级的进程在用户模式下的执行时间。
system:进程在内核模式下的执行时间。
idle:空转时间。
iowait:等待I/O完成的时间。
irq:处理中断请求花费的时间。
softirq:处理软中断请求花费的时间。
"intr"一行给出了从启动到现在的中断服务次数,每一次可能的系统中断。第一列是总的中断服务次数;其它后续的列是各种特殊的中断总数。
"ctxt"一行给出的是从启动到现在所有的CPU进行上下文切换的总次数。
"btime"一行给出的是系统启动的时间,从Unix纪元(1970年1月1日0时0秒)开始的秒数。
"processes"一行给出的是创建的进程和线程总数,包括(但不限于)通过调用fork()和clone()系统调用创建的那些进程和线程。
"procs_running"给出的是当前正在运行的进程数。
"procs_blocked"给出的是当前被阻塞的进程数,正在等待I/O完成。
二、取得虚拟内存统计信息(相关文件/proc/vmstat)
在一个系统中/proc/vmstat文件显示的是从内核导出的虚拟内存的统计信息。大多数参数在配置了VM_EVENT_COUNTERS选项后编译内核才有效。这是因为大多数参数对于内核本身是没用的,但对于调试和统计信息有用。
各行解释如下:
$ cat vmstat
nr_dirty 3 #脏页数
nr_writeback 0 #回写页数
nr_unstable 0 #不稳定页数
nr_page_table_pages 894 #分配到页表的页数
nr_mapped 86854 #映射到文件的页数
nr_slab 4492 #由内核切片器分配的页数
pgpgin 2433258 #从启动到现在读入的内存页数
pgpgout 2157211 #从启动到现在换出的内存页数
pswpin 43240 #从启动到现在读入的交换分区页数
pswpout 69525 #从启动到现在换出的交换分区页数
#每个存储区分配的页数
pgalloc_high 0 #从启动到现在高址存储区分配的页数
pgalloc_normal 170951852 #从启动到现在普通存储区分配的页数
pgalloc_dma 1892977 #从启动到现在DMA存储区分配的页数
pgfree 172846757 #从启动到现在释放的页数
pgactivate 504252 #从启动到现在激活的页数
pgdeactivate 421772 #从启动到现在去激活的页数
pgfault 21166511 #从启动到现在二级页面错误数
pgmajfault 21868 #从启动到现在一级页面错误数
pgrefill_high 0 #从启动到现在高址存储区再填充的页面数
pgrefill_normal 2280369 #从启动到现在普通存储区再填充的页面数
pgrefill_dma 153904 #从启动到现在DMA存储区再填充的页面数
pgsteal_high 0 #从启动到现在回收高址存储区用于其它目的的页面数
pgsteal_normal 505128 #从启动到现在回收普通存储区用于其它目的的页面数
pgsteal_dma 53444 #从启动到现在回收DMA存储区用于其它目的的页面数
pgscan_kswapd_high 0 #从启动到现在kswapd后台进程扫描的高址存储区页面数
pgscan_kswapd_normal 579051 #从启动到现在kswapd后台进程扫描的普通存储区页面数
pgscan_kswapd_dma 59593 #从启动到现在kswapd后台进程扫描的DMA存储区页面数
pgscan_direct_high 0 #从启动到现在高址存储区被直接回收的页面数
pgscan_direct_normal 131406 #从启动到现在普通存储区被直接回收的页面数
pgscan_direct_dma 11526 #从启动到现在DMA存储区被直接回收的页面数
pginodesteal 2191 #从启动到现在通过释放i节点回收的页面数
slabs_scanned 498816 #从启动到现在被扫描的切片数
kswapd_steal 454737 #从启动到现在由kswapd回收用于其它目的的页面数
kswapd_inodesteal 204421 #从启动到现在由kswapd通过释放i节点回收的页面数
pageoutrun 13634 #从启动到现在通过kswapd调用来回收的页面数
allocstall 2513 #从启动到现在请求直接回收的页面数
pgrotated 69535 #从启动到现在轮换的页面数
参考: https://www.kernel.org/doc/Documentation/vm/transhuge.txt
As the system ages, allocating huge pages may be expensive as the
system uses memory compaction to copy data around memory to free a
huge page for use. There are some counters in /proc/vmstat to help
monitor this overhead.
compact_stall is incremented every time a process stalls to run
memory compaction so that a huge page is free for use.
compact_success is incremented if the system compacted memory and
freed a huge page for use.
compact_fail is incremented if the system tries to compact memory
but failed.
compact_pages_moved is incremented each time a page is moved. If
this value is increasing rapidly, it implies that the system
is copying a lot of data to satisfy the huge page allocation.
It is possible that the cost of copying exceeds any savings
from reduced TLB misses.
compact_pagemigrate_failed is incremented when the underlying mechanism
for moving a page failed.
compact_blocks_moved is incremented each time memory compaction examines
a huge page aligned range of pages.
#cat /proc/vmstat | grep com
compact_migrate_scanned 0
compact_free_scanned 0
compact_isolated 0
compact_stall 0
compact_fail 0
compact_success 0
三、取得物理内存信息(相关文件/proc/meminfo)
/proc/meminfo文件是从内核导出的当前内存的使用情况。下面是一些关键项的解释。
$cat /proc/meminfo
MemTotal: 515668 kB #总的物理内存大小
MemFree: 2684 kB #可用物理内存大小,因为大量的内存被用于高速缓存,所以这个数比较小,这个值等于下面的HighFree + LowFree的值
Buffers: 8928 kB #缓冲区大小
Cached: 225684 kB #用于高速缓存的大小
SwapCached: 74196 kB #用于高速缓存的交换分区大小
Active: 412920 kB #活动内存量
Inactive: 73988 kB #不活动内存量
HighTotal: 0 kB #高阶内存总数,高阶内存是指超过860M(大约)物理内存以后的内存
HighFree: 0 kB #高阶内存可用内存总数
LowTotal: 515668 kB #低阶内存总数
LowFree: 2684 kB #低阶内存区域的可用内存总数,这是内核可以直接寻址的内存
SwapTotal: 522072 kB #交换分区大小
SwapFree: 365588 kB #可用交换分区大小
Dirty: 28 kB #脏内存,可能要写到磁盘或者交换分区的内存
Writeback: 0 kB
Mapped: 360956 kB
Slab: 17244 kB
Committed_AS: 947452 kB #最坏情况下使用的内存数的一个估计值
PageTables: 3704 kB #内存页表数
VmallocTotal: 499704 kB
VmallocUsed: 3088 kB
VmallocChunk: 496356 kB
HugePages_Total: 0
HugePages_Free: 0
Hugepagesize: 4096 kB
四、取得磁盘信息(相关文件/proc/diskstats或者/sys/block/hd?/stat)
从2.4.20(和某些更早的打补丁的版本)和2.5.45以来为了帮助测量磁盘作业引入了更多的磁盘统计信息。诸如sar和iostat这样的工具一般会说明这些和为你做这些工作,但是如果你有兴趣创建自己的工具,知道在哪里取到这些信息将会非常有用。
$cat /proc/diskstats
...
22 0 hdc 159807 57894 6328277 1476593 179991 467858 5184662 2664218 0 886604 4140851
...
$cat /sys/block/hdc/stat
159807 57894 6328277 1476593 179989 467844 5184534 2664218 0 886604 4140851
/proc/diskstats文件比/sys/block/hdc/stat文件多3个域,从左至右分别对应主设备号,次设备号和设备名称。后续的11个域在这两个文件里是相同的,它们的函义将在下面解释。除了第9个域,所有的域都是从启动时的累积值。
第1个域:读磁盘的次数,成功完成读的总次数。
第2个域:合并读次数, field 6 – 合并写次数。为了效率可能会合并相邻的读和写。从而两次4K的读在它最终被处理到磁盘上之前可能会变成一次8K的读,才被计数(和排队),因此只有一次I/O操作。这个域使你知道这样的操作有多频繁。
第3个域:读扇区的次数,成功读过的扇区总次数。
第4个域:读花费的毫秒数,这是所有读操作所花费的毫秒数(用__make_request()到end_that_request_last()测量)。
第5个域:写完成的次数,成功写完成的总次数。
第7个域:写扇区的次数,成功写扇区总次数。
第8个域:写花费的毫秒数,这是所有写操作所花费的毫秒数(用__make_request()到end_that_request_last()测量)。
第9个域:I/O的当前进度,只有这个域应该是0。当请求被交给适当的request_queue_t时增加和请求完成时减小。
第10个域:花在I/O操作上的毫秒数,这个域会增长只要field 9不为0。
第11个域:加权, 花在I/O操作上的毫秒数,在每次I/O开始,I/O结束,I/O合并时这个域都会增加。这可以给I/O完成时间和存储那些可以累积的提供一个便利的测量标准。
五、取各个网卡的流量统计信息(相关文件/proc/net/dev)
/proc/net/dev文件的每一行对应一个网卡的统计信息,各个域从左到右的内容如下:
网卡接口名(如eth0)
#接收
收到的字节数
收到的数据包总数
收到的误码数
收到的丢失误码数
收到的FIFO误码数
收到的帧误码
收到的压缩字节数
收到的多播误码数
#发送
传输的字节数
传输的数据包总数
传输误码总数
传输丢失误码
传输FIFO误码
传输冲突误码
传输载波误码
传输压缩字节数
六、取得系统的运行时间(相关文件/proc/uptime)
$ cat /proc/uptime
533263.88 519004.52
/proc/uptime文件里包含两个数字,第一个是系统正常运行的时间,第二个是从启动到现在系统空转的时间。从这里可以看到我的系统绝大部份时间都是空转,并不忙。
七、取得系统的负载信息(相关文件/proc/loadavg)
$cat /proc/loadavg
0.50 0.48 0.29 1/128 12250
从左至右的内容分别是系统过去1分钟的平均负载、过去5分钟的平均负载、过去15分钟的平均负载、正在运行的任务数/当前总任务数、上一次创建进程使用的PID号。