vmstat
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 310596 24796 143780 0 0 933 89 1044 119 3 21 72 4 0
1)procs:
r:代表正在运行的进程数.
b:代表处在不可屏蔽中断的进程数.
2)memory:
swpd:已使用swap的空间大小.
free:空闲的内存.
buff:内存中buffer的大小.
cache:内存中cache的大小.
3)swap
si:从swap读出的内存,也就是主缺页,这个值是一个比率,即每秒读了多少KB.
so:置换到swap的内存,这个值是一个比率,即每秒写了多少KB.
4)io
bi:从磁盘读数据,这个值是一个比率,即每秒读了多少BLOCK.
bo:写数据到磁盘,这个值是一个比率,即每秒写了多少BLOCK.
5)system
in:每秒中断的次数.
cs:每秒转换上下文的次数.
6)
us:用户态进程使用CPU的百分比.
sy:内核态进程使用CPU的百分比.
id:处于空闲的CPU百分比.
wa:系统等待IO的CPU时间百分比.
st:来自于一个虚拟机偷取的CPU时间的百分比.
二)系统监控的实验:
实例一,大量的算术运算
本程序会进入一个死循环,不断的进行求平方根的操作,模拟大量的算术运算的环境.
测试源程序如下:
#include <stdio.h>
#include <math.h>
#include <unistd.h>
#include <stdlib.h>
void
run_status(void)
{
double pi = M_PI;
double pisqrt;
long i;
while(1){
pisqrt = sqrt(pi);
}
}
int
main (void)
{
run_status();
exit(EXIT_SUCCESS);
}
gcc run.c -o run -lm
./run&
运行:
vmstat 1
注:我们的程序不断的进行算术运算,r的值由0变成了1,而cpu的用户态利用率也达到了100%.如下:
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 304592 25244 147800 0 0 0 0 1010 31 0 1 99 0 0
0 0 0 304592 25244 147800 0 0 0 0 1020 37 0 0 100 0 0
1 0 0 304592 25244 147800 0 0 0 36 1016 46 69 1 30 0 0
1 0 0 304592 25244 147800 0 0 0 0 1067 56 100 0 0 0 0
1 0 0 304592 25244 147800 0 0 0 0 1010 31 100 0 0 0 0
实例二,大量的系统调用
本脚本会进入一个死循环,不断的执行cd命令,从而模拟大量系统调用的环境
测试脚本如下:
#!/bin/bash
while (true)
do
cd ;
done
chmod +x loop.sh
./loop.sh
运行:
vmstat 1
注:程序不断的调用cd命令,此时进程不断的进行上下文切换,所以cs的值会骤然提高,而cpu的内核态利用率也会达到98%左右.如下:
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 304592 25248 147804 0 0 111 15 1025 179 20 20 59 0 0
0 0 0 304592 25248 147804 0 0 0 0 1013 36 0 0 100 0 0
1 0 0 304592 25248 147816 0 0 0 0 1015 422 1 72 27 0 0
2 0 0 304592 25248 147816 0 0 0 0 1012 544 3 97 0 0 0
1 0 0 304592 25248 147816 0 0 0 0 1007 522 3 97 0 0 0
1 0 0 304592 25248 147816 0 0 0 64 1015 523 3 97 0 0 0
2 0 0 304592 25248 147816 0 0 0 0 1003 572 2 98 0 0 0
1 0 0 304592 25248 147816 0 0 0 0 1012 1263 2 98 0 0 0
1 0 0 304592 25248 147816 0 0 0 0 1006 1264 3 97 0 0 0
1 0 0 304592 25248 147816 0 0 0 0 1015 1249 3 97 0 0 0
实例三,大量的io操作
我们用dd命令,从/dev/zero读数据,写入到/tmp/data文件中,如下:
dd if=/dev/zero of=/tmp/data bs=1M count=1000
运行:
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 302160 25868 149004 0 0 77 116 1027 151 14 17 69 0 0
1 0 0 302160 25868 149004 0 0 0 0 1018 35 0 1 99 0 0
3 0 0 134884 26032 311628 0 0 0 109872 1423 102 0 100 0 0 0
1 0 0 14596 26148 428808 0 0 0 117208 1372 120 0 100 0 0 0
1 0 0 6224 22908 440592 0 0 4 64944 1305 322 0 98 0 2 0
1 0 0 5976 21836 441016 0 0 4 79072 1447 162 0 51 0 49 0
0 2 0 5716 21956 439672 0 0 4 79016 1431 374 0 81 0 19 0
2 2 0 6180 22044 438064 0 0 0 61432 1392 285 0 61 0 39 0
2 2 0 6912 22104 436828 0 0 4 73980 1486 253 1 59 0 40 0
0 4 0 5876 14132 448856 0 0 8 63784 1378 313 0 69 0 31 0
0 2 4 5980 4140 457860 0 0 0 46756 1399 274 0 65 0 35 0
1 3 4 6060 3892 457580 0 0 8 69876 1398 214 0 46 0 54 0
1 4 4 6120 2872 457348 0 0 0 59920 1364 327 0 71 0 29 0
注:dd不断的向磁盘写入数据,所以bo的值会骤然提高,而cpu的wait数值也变高,说明由于大量的IO操作,系统的瓶径出现在低速的设备上.
由于对文件系统的写入操作,cache也从149004KB提高到了457348KB,又由于大量的写中断调用,in的值也从1018提高到1364.
接下来我们还用dd命令,这回从/tmp/data文件读,写到/dev/null文件中,如下:
dd if=/tmp/test1 of=/dev/null bs=1M
运行:
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 60 7056 2492 464560 0 0 177 517 1028 116 10 12 78 1 0
0 0 60 7056 2492 464560 0 0 0 0 1006 32 0 0 100 0 0
0 1 60 5768 2296 465032 0 4 94340 4 1514 252 0 65 17 18 0
1 1 60 5876 2220 466032 0 0 150148 56 1770 306 0 93 0 7 0
0 1 60 5792 2180 467152 0 0 98872 0 1598 281 0 81 0 19 0
0 1 60 6308 988 469816 0 52 89556 52 1722 303 0 88 0 12 0
2 1 60 5620 1004 470488 0 0 79052 0 1671 690 0 72 0 28 0
0 1 60 6548 1028 469540 0 0 67392 4 1535 657 1 66 0 33 0
1 1 60 5648 1060 470588 0 0 47408 16 1400 482 0 44 0 56 0
0 1 60 6368 1088 469836 0 0 70212 0 1561 666 0 66 0 34 0
注:dd不断的从/tmp/data磁盘文件中读取数据,所以bi的值会骤然变高,最后我们看到b(不可中断进程数)也由0变成了1.
接下来我们继续用dd命令,把数据写到/dev/ram1里,如下:
dd if=/dev/zero of=/dev/ram1 bs=1M count=16
16+0 records in
16+0 records out
16777216 bytes (17 MB) copied, 0.0635522 seconds, 264 MB/s
运行:
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 60 6156 6256 466280 0 0 366 480 1029 111 9 11 79 1 0
0 0 60 6156 6256 466280 0 0 0 0 1011 32 0 0 100 0 0
0 0 60 6156 6256 466292 0 0 12 0 1031 65 0 3 96 1 0
0 0 60 6156 6264 466284 0 0 0 48 1022 48 0 1 99 0 0
0 0 60 6148 17920 454652 0 0 0 4 1021 81 0 8 92 0 0
0 0 60 6148 17920 454652 0 0 0 0 1013 32 1 0 99 0 0
0 0 60 6148 17920 454652 0 0 0 0 1016 36 0 1 99 0 0
0 0 60 6148 17920 454652 0 0 0 0 1006 31 0 0 100 0 0
0 0 60 6148 17920 454652 0 0 0 0 1026 42 0 0 100 0 0
注:dd从/dev/zero读取数据,写入到/dev/ram1里面,由于/dev/ram1是设备节点,所以buff会增加.
实例四:大量的占用内存
本程序会不断分配内存,直到系统崩溃.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
void *ptr;
int n = 0;
while (1){
ptr = malloc(0x100000);
if (ptr == NULL)
break;
memset(ptr, 1, 0x100000);
printf("malloced %d MB\n", ++n);
}
pause();
}
gcc callmem.c -o callmem
./callmem
运行:
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 7512 18796 451064 0 0 346 442 1028 105 8 10 81 1 0
0 0 0 7512 18796 451064 0 0 0 0 1012 36 0 1 99 0 0
2 0 0 6096 18704 417676 0 0 0 0 1042 169 0 88 12 0 0
1 0 0 5896 18616 379356 0 0 0 0 1048 183 1 99 0 0 0
1 0 0 6324 18532 340796 0 0 0 36 1043 215 1 99 0 0 0
1 0 0 6376 18444 302372 0 0 0 0 1048 195 0 100 0 0 0
1 0 0 6036 18384 264904 0 0 0 0 1040 187 1 99 0 0 0
1 0 0 5784 18384 228560 0 0 0 0 1046 175 1 99 0 0 0
1 0 0 6532 18372 190316 0 0 0 0 1041 188 1 99 0 0 0
1 0 0 6084 18364 153804 0 0 0 0 1047 187 0 100 0 0 0
1 0 0 6256 18368 115992 0 0 0 12 1041 195 1 99 0 0 0
1 0 0 6580 17852 77868 0 0 0 0 1050 196 1 99 0 0 0
1 1 0 4892 17304 39556 0 0 0 0 1044 157 0 100 0 0 0
1 1 0 5252 17304 18676 0 0 0 0 1037 81 1 99 0 0 0
1 0 9236 6156 16456 7580 0 9172 0 9196 1092 131 1 74 0 25 0
1 0 56008 6860 16456 7620 0 46772 0 46772 1394 399 1 96 0 3 0
2 1 103600 6488 16464 7600 0 47652 0 47668 1416 395 2 96 0 2 0
1 1 162644 6580 16464 7536 0 59044 0 59044 1300 333 2 92 0 6 0
1 0 197980 6408 16464 5876 0 35340 0 35340 1330 259 3 89 0 8 0
2 4 230372 4920 16468 2876 0 32392 4 32392 1299 293 2 96 0 2 0
2 2 269352 5824 16472 1304 0 38980 252 38980 1306 285 2 90 0 8 0
2 2 305656 4936 16468 1392 88 36304 216 36304 1310 317 1 87 0 12 0
3 5 361100 5136 16472 1352 96 55444 96 55456 1301 297 2 91 0 7 0
5 3 404796 6820 16488 1760 96 43696 524 43696 1282 186 2 82 0 16 0
注:我们看到cache迅速减少,而swpd迅速增加,这是因为系统为了分配给新的程序,而从cache(文件系统缓存)回收空间,当空间依然不足时,会用到swap空间.
而于此同时,si/so也会增加,尤其是so,而swap属于磁盘空间,所以bo也会增加.
最后:st这个值来自一个虚拟机偷到的时间,在Linux 2.6.11内核之前,没有这个值.
实例五:又一个大量分配内存例子
我们这个例子为了说明active/inactivte的作用,
源程序如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int
main (int argc, char *argv[])
{
if (argc != 2)
exit (0);
size_t mb = strtoul(argv[1],NULL,0);
size_t nbytes = mb * 0x100000;
char *ptr = (char *) malloc(nbytes);
if (ptr == NULL){
perror("malloc");
exit (EXIT_FAILURE);
}
size_t i;
const size_t stride = sysconf(_SC_PAGE_SIZE);
for (i = 0;i < nbytes; i+= stride) {
ptr[i] = 0;
}
printf("allocated %d mb\n", mb);
pause();
return 0;
}
gcc act.c -o act -lrt
./act 100
运行:
vmstat -a 1
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
r b swpd free inact active si so bi bo in cs us sy id wa st
0 0 0 363868 79488 47724 5 160 291 504 1032 95 6 9 83 1 0
0 0 0 363868 79488 47728 0 0 0 0 1010 32 0 0 100 0 0
0 0 0 363868 79488 47728 0 0 0 0 1014 34 0 0 100 0 0
1 0 0 333924 79492 77736 0 0 8 36 1014 44 0 75 24 1 0
1 0 0 293252 79500 118388 0 0 0 0 1011 34 0 100 0 0 0
0 0 0 261384 79500 150140 0 0 0 0 1009 36 0 78 22 0 0
0 0 0 261384 79500 150192 0 0 0 0 1015 33 0 1 99 0 0
0 0 0 261384 79500 150192 0 0 0 0 1008 30 0 0 100 0 0
0 0 0 261384 79500 150192 0 0 0 0 1015 32 0 0 100 0 0
0 0 0 363436 79500 47732 0 0 0 12 1018 45 0 2 98 0 0
0 0 0 363436 79508 47732 0 0 0 0 1011 55 0 1 99 0 0
0 0 0 363436 79508 47732 0 0 0 0 1008 29 0 0 100 0 0
注:程序运行时系统给它分配了100MB的内存,所以此时的active从47728kb变到了150192kb.
三)vmstat用法:
查看系统已经fork了多少次
vmstat -f
processes 114688
注:这个数据是从/proc/stat中的processes字段里取得的.
查看内存的active和inactive
vmstat -a
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
r b swpd free inact active si so bi bo in cs us sy id wa st
0 0 0 361952 80536 48396 5 140 255 441 1031 87 6 8 85 1 0
注:inact和active的数据来自于/proc/meminfo.
查看内存使用的详细信息
vmstat -s
515600 total memory
154020 used memory
48396 active memory
80600 inactive memory
361580 free memory
46376 buffer memory
57352 swap cache
1052248 total swap
0 used swap
1052248 free swap
31352 non-nice user cpu ticks
167 nice user cpu ticks
43234 system cpu ticks
489636 idle cpu ticks
5509 IO-wait cpu ticks
1243 IRQ cpu ticks
1751 softirq cpu ticks
0 stolen cpu ticks
1451094 pages paged in
2514952 pages paged out
6822 pages swapped in
198826 pages swapped out
5905614 interrupts
498241 CPU context switches
1300715746 boot time
114723 forks
注:这些信息的分别来自于/proc/meminfo,/proc/stat和/proc/vmstat.
查看磁盘的读/写
vmstat -d
disk- ------------reads------------ ------------writes----------- -----IO------
total merged sectors ms total merged sectors ms cur sec
ram0 0 0 0 0 0 0 0 0 0 0
ram1 0 0 0 0 0 0 0 0 0 0
ram2 0 0 0 0 0 0 0 0 0 0
ram3 0 0 0 0 0 0 0 0 0 0
ram4 0 0 0 0 0 0 0 0 0 0
ram5 0 0 0 0 0 0 0 0 0 0
ram6 0 0 0 0 0 0 0 0 0 0
ram7 0 0 0 0 0 0 0 0 0 0
ram8 0 0 0 0 0 0 0 0 0 0
ram9 0 0 0 0 0 0 0 0 0 0
ram10 0 0 0 0 0 0 0 0 0 0
ram11 0 0 0 0 0 0 0 0 0 0
ram12 0 0 0 0 0 0 0 0 0 0
ram13 0 0 0 0 0 0 0 0 0 0
ram14 0 0 0 0 0 0 0 0 0 0
ram15 0 0 0 0 0 0 0 0 0 0
sda 26411 18657 2900913 144728 22982 605889 5030968 3128488 0 117
hdc 143 94 1276 357 0 0 0 0 0 0
fd0 0 0 0 0 0 0 0 0 0 0
md0 0 0 0 0 0 0 0 0 0 0
注:这些信息主要来自于/proc/diskstats.
merged:表示一次来自于合并的写/读请求,一般系统会把多个连接/邻近的读/写请求合并到一起来操作.
查看/dev/sda1磁盘的读/写
vmstat -p /dev/sda1
sda1 reads read sectors writes requested writes
35215 2842778 430114 3440912
注:这些信息主要来自于/proc/diskstats
reads:来自于这个分区的读的次数.
read sectors:来自于这个分区的读扇区的次数.
writes:来自于这个分区的写的次数.
requested writes:来自于这个分区的写请求次数.
查看系统的slab信息
vmstat -m
Cache Num Total Size Pages
rpc_buffers 8 8 2048 2
rpc_tasks 8 20 192 20
rpc_inode_cache 6 9 448 9
ip_fib_alias 14 113 32 113
ip_fib_hash 14 113 32 113
fib6_nodes 24 113 32 113
ip6_dst_cache 16 30 256 15
ndisc_cache 1 20 192 20
RAWv6 4 11 704 11
UDPv6 2 6 640 6
tw_sock_TCPv6 0 0 128 30
request_sock_TCPv6 0 0 128 30
TCPv6 3 3 1280 3
dm_tio 0 0 16 203
dm_io 0 0 20 169
jbd_4k 0 0 4096 1
scsi_cmd_cache 1 12 320 12
sgpool-128 32 32 2048 2
sgpool-64 32 32 1024 4
sgpool-32 32 32 512 8
sgpool-16 32 45 256 15
sgpool-8 34 60 128 30
scsi_io_context 0 0 104 37
ext3_inode_cache 21829 21832 492 8
ext3_xattr 36 78 48 78
journal_handle 2 169 20 169
journal_head 63 72 52 72
revoke_table 2 254 12 254
revoke_record 0 0 16 203
uhci_urb_priv 0 0 28 127
UNIX 56 63 448 9
flow_cache 0 0 128 30
cfq_ioc_pool 0 0 92 42
cfq_pool 0 0 96 40
crq_pool 0 0 44 84
deadline_drq 63 252 44 84
as_arq 0 0 56 67
mqueue_inode_cache 1 7 576 7
isofs_inode_cache 2 20 368 10
hugetlbfs_inode_cache 1 11 340 11
ext2_inode_cache 0 0 476 8
ext2_xattr 0 0 48 78
dnotify_cache 2 169 20 169
Cache Num Total Size Pages
dquot 0 0 128 30
eventpoll_pwq 1 101 36 101
eventpoll_epi 1 30 128 30
inotify_event_cache 0 0 28 127
inotify_watch_cache 1 92 40 92
kioctx 0 0 192 20
kiocb 0 0 128 30
fasync_cache 0 0 16 203
shmem_inode_cache 239 243 436 9
posix_timers_cache 0 0 88 44
uid_cache 5 59 64 59
ip_mrt_cache 0 0 128 30
tcp_bind_bucket 7 203 16 203
inet_peer_cache 0 0 64 59
secpath_cache 0 0 32 113
xfrm_dst_cache 0 0 320 12
ip_dst_cache 5 15 256 15
arp_cache 2 20 192 20
RAW 2 7 512 7
UDP 8 14 512 7
tw_sock_TCP 0 0 128 30
request_sock_TCP 0 0 128 30
TCP 6 7 1152 7
blkdev_ioc 6 127 28 127
blkdev_queue 20 20 956 4
blkdev_requests 100 184 172 23
biovec-256 7 8 3072 2
biovec-128 7 10 1536 5
biovec-64 7 10 768 5
biovec-16 7 20 192 20
biovec-4 7 59 64 59
biovec-1 71 406 16 203
bio 342 390 128 30
utrace_engine_cache 0 0 32 113
utrace_cache 0 0 32 113
sock_inode_cache 104 110 384 10
skbuff_fclone_cache 10 10 384 10
skbuff_head_cache 120 120 192 20
file_lock_cache 3 40 96 40
Acpi-Operand 448 552 40 92
Acpi-ParseExt 0 0 44 84
Acpi-Parse 0 0 28 127
Acpi-State 0 0 44 84
Cache Num Total Size Pages
Acpi-Namespace 337 338 20 169
delayacct_cache 78 78 48 78
taskstats_cache 19 53 72 53
proc_inode_cache 19 99 356 11
sigqueue 17 27 144 27
radix_tree_node 2319 2422 276 14
bdev_cache 23 28 512 7
sysfs_dir_cache 2928 2940 44 84
mnt_cache 28 30 128 30
inode_cache 692 792 340 11
dentry_cache 24563 24563 136 29
filp 830 980 192 20
names_cache 3 3 4096 1
avc_node 14 72 52 72
selinux_inode_security 636 780 48 78
key_jar 11 30 128 30
idr_layer_cache 100 116 136 29
buffer_head 8996 9000 52 72
mm_struct 61 63 448 9
vm_area_struct 1788 1932 84 46
fs_cache 59 59 64 59
files_cache 60 60 384 10
signal_cache 81 81 448 9
sighand_cache 72 72 1344 3
task_struct 78 78 1360 3
anon_vma 794 1016 12 254
pgd 47 47 4096 1
pid 92 101 36 101
size-131072(DMA) 0 0 131072 1
size-131072 0 0 131072 1
size-65536(DMA) 0 0 65536 1
size-65536 1 1 65536 1
size-32768(DMA) 0 0 32768 1
size-32768 1 1 32768 1
size-16384(DMA) 0 0 16384 1
size-16384 1 1 16384 1
size-8192(DMA) 0 0 8192 1
size-8192 0 0 8192 1
size-4096(DMA) 0 0 4096 1
size-4096 92 92 4096 1
size-2048(DMA) 0 0 2048 2
size-2048 234 234 2048 2
size-1024(DMA) 0 0 1024 4
Cache Num Total Size Pages
size-1024 176 176 1024 4
size-512(DMA) 0 0 512 8
size-512 264 264 512 8
size-256(DMA) 0 0 256 15
size-256 300 300 256 15
size-128(DMA) 0 0 128 30
size-128 1200 1200 128 30
size-64(DMA) 0 0 64 59
size-32(DMA) 0 0 32 113
size-64 1013 1180 64 59
size-32 1856 1921 32 113
kmem_cache 140 150 256 15
注:这组信息来自于/proc/slabinfo
slab:由于内核会有许多小对象,这些对象构造销毁十分频繁,比如i-node,dentry,这些对象如果每次构建的时候就向内存要一个页(4kb),而其实只有几个字节,这样就会非常浪费,为了解决这个问题,就引入了一种新的机制来处理在同一个页框中如何分配小存储区,而slab可以对小对象进行分配,这样就不用为每一个对象分配页框,从而节省了空间,内核对一些小对象创建析构很频繁,slab对这些小对象进行缓冲,可以重复利用,减少内存分配次数.