Mercurial > hg > toybox
comparison toys/vmstat.c @ 559:120b3dde7cf4
Adding vmstat
author | Elie De Brauwer <eliedebrauwer@gmail.com> |
---|---|
date | Mon, 09 Apr 2012 13:31:44 +0200 |
parents | |
children | c97e338a4126 |
comparison
equal
deleted
inserted
replaced
558:8a1d45dd8af1 | 559:120b3dde7cf4 |
---|---|
1 /* vi: set sw=4 ts=4: | |
2 * | |
3 * vmstat.c - Report virtual memory statistics. | |
4 * | |
5 * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> | |
6 * | |
7 * Not in SUSv4. | |
8 | |
9 USE_VMSTAT(NEWTOY(vmstat, ">2n", TOYFLAG_BIN)) | |
10 | |
11 config VMSTAT | |
12 bool "vmstat" | |
13 default y | |
14 help | |
15 usage: vmstat [-n] [delay [count]] | |
16 -n Display the header only once | |
17 delay The delay between updates in seconds, when not specified | |
18 the average since boot is displayed. | |
19 count Number of updates to display, the default is inifinite. | |
20 */ | |
21 | |
22 #include "toys.h" | |
23 | |
24 void read_proc_stat(unsigned int * proc_running, unsigned int * proc_blocked, | |
25 uint64_t * sys_irq, uint64_t * sys_ctxt, | |
26 uint64_t * cpu_user, uint64_t * cpu_sys, uint64_t * cpu_idle, uint64_t * cpu_wait) | |
27 { | |
28 char * off; | |
29 uint64_t c_user, c_nice, c_sys, c_irq, c_sirq; | |
30 int fd = xopen("/proc/stat", O_RDONLY); | |
31 if (fdlength(fd) > sizeof(toybuf)) | |
32 error_exit("/proc/stat is too large"); | |
33 xread(fd, toybuf, sizeof(toybuf)); | |
34 | |
35 off = strstr(toybuf, "cpu "); | |
36 // Ignoring steal and guest fields for now. | |
37 if (off) sscanf(off, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu", &c_user, &c_nice, &c_sys, cpu_idle, cpu_wait, &c_irq, &c_sirq); | |
38 *cpu_user = c_user + c_nice; | |
39 *cpu_sys = c_sys + c_irq + c_sirq; | |
40 off = strstr(toybuf, "intr"); | |
41 if (off) sscanf(off, "intr %Lu", sys_irq); | |
42 | |
43 off = strstr(toybuf, "ctxt"); | |
44 if (off) sscanf(off, "ctxt %Lu", sys_ctxt); | |
45 | |
46 off = strstr(toybuf, "procs_running"); | |
47 if (off) sscanf(off, "procs_running %u", proc_running); | |
48 (*proc_running)--; // look, i'm invisible. | |
49 | |
50 off = strstr(toybuf, "procs_blocked"); | |
51 if (off) sscanf(off, "procs_blocked %u", proc_blocked); | |
52 | |
53 close(fd); | |
54 } | |
55 | |
56 void read_proc_meminfo(unsigned long * mem_swapped, unsigned long * mem_free, | |
57 unsigned long * mem_buff, unsigned long * mem_cache) | |
58 { | |
59 char * off; | |
60 unsigned long swap_total, swap_free; | |
61 int fd = xopen("/proc/meminfo", O_RDONLY); | |
62 if (fdlength(fd) > sizeof(toybuf)) | |
63 error_exit("/proc/meminfo is too large"); | |
64 xread(fd, toybuf, sizeof(toybuf)); | |
65 | |
66 off = strstr(toybuf, "MemFree"); | |
67 if (off) sscanf(off, "MemFree: %lu kB", mem_free); | |
68 | |
69 off = strstr(toybuf, "Buffers"); | |
70 if (off) sscanf(off, "Buffers: %lu kB", mem_buff); | |
71 | |
72 off = strstr(toybuf, "Cached"); | |
73 if (off) sscanf(off, "Cached: %lu kB", mem_cache); | |
74 | |
75 off = strstr(toybuf, "SwapFree"); | |
76 if (off) sscanf(off, "SwapFree: %lu kB", &swap_free); | |
77 | |
78 off = strstr(toybuf, "SwapTotal"); | |
79 if (off) sscanf(off, "SwapTotal: %lu kB", &swap_total); | |
80 *mem_swapped = swap_total - swap_free; | |
81 | |
82 close(fd); | |
83 } | |
84 | |
85 void read_proc_vmstat(unsigned long * io_pages_in, unsigned long * io_pages_out, unsigned long * swap_bytes_in, unsigned long * swap_bytes_out) | |
86 { | |
87 char * off; | |
88 unsigned long s_pages_in, s_pages_out; | |
89 unsigned long pagesize_kb = sysconf(_SC_PAGESIZE) / 1024L; | |
90 int fd = xopen("/proc/vmstat", O_RDONLY); | |
91 if (fdlength(fd) > sizeof(toybuf)) | |
92 error_exit("/proc/vmstat is too large"); | |
93 xread(fd, toybuf, sizeof(toybuf)); | |
94 | |
95 off = strstr(toybuf, "pgpgin"); | |
96 if (off) sscanf(off, "pgpgin %lu", io_pages_in); | |
97 | |
98 off = strstr(toybuf, "pgpgout"); | |
99 if (off) sscanf(off, "pgpgout %lu", io_pages_out); | |
100 | |
101 off = strstr(toybuf, "pswpin"); | |
102 if (off) sscanf(off, "pswpin %lu", &s_pages_in); | |
103 *swap_bytes_in = s_pages_in * pagesize_kb; | |
104 | |
105 off = strstr(toybuf, "pswpout"); | |
106 if (off) sscanf(off, "pswpout %lu", &s_pages_out); | |
107 *swap_bytes_out = s_pages_out * pagesize_kb; | |
108 | |
109 close(fd); | |
110 } | |
111 | |
112 void vmstat_main(void) | |
113 { | |
114 const char fmt[] = "%2u %2u %6lu %6lu %6lu %6lu %4u %4u %5u %5u %4u %4u %2u %2u %2u %2u\n"; | |
115 unsigned int loop_num = 0, loop_max_num = 0, loop_delay = 0; | |
116 unsigned int running = 0, blocked = 0; | |
117 unsigned long mem_swap = 0, mem_free = 0, mem_buff = 0, mem_cache = 0; | |
118 unsigned long io_pages_in[2], io_pages_out[2], swap_bytes_in[2], swap_bytes_out[2]; | |
119 uint64_t sys_irq[2], sys_ctxt[2], cpu_user[2], cpu_sys[2], cpu_idle[2], cpu_wait[2]; | |
120 int first_run = 1; | |
121 int no_header = toys.optflags & 0x1; | |
122 | |
123 if (toys.optc >= 1) | |
124 loop_delay = atoi(toys.optargs[0]); | |
125 if (toys.optc >= 2) | |
126 loop_max_num = atoi(toys.optargs[1]); | |
127 | |
128 if (loop_max_num < 0 || loop_delay < 0) | |
129 error_exit("Invalid arguments"); | |
130 | |
131 while(1) { | |
132 uint64_t total_jif; | |
133 int idx = loop_num%2; | |
134 | |
135 if(first_run || (!(loop_num % 22) && !no_header)) { | |
136 printf("procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----\n"); | |
137 printf(" r b swpd free buff cache si so bi bo in cs us sy id wa\n"); | |
138 } | |
139 | |
140 read_proc_stat(&running, &blocked, &sys_irq[idx], &sys_ctxt[idx], &cpu_user[idx], | |
141 &cpu_sys[idx], &cpu_idle[idx], &cpu_wait[idx]); | |
142 read_proc_meminfo(&mem_swap, &mem_free, &mem_buff, &mem_cache); | |
143 read_proc_vmstat(&io_pages_in[idx], &io_pages_out[idx], &swap_bytes_in[idx], &swap_bytes_out[idx]); | |
144 | |
145 if (first_run) { | |
146 struct sysinfo inf; | |
147 sysinfo(&inf); | |
148 first_run = 0; | |
149 total_jif = cpu_user[idx] + cpu_idle[idx] + cpu_wait[idx]; | |
150 printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache, | |
151 (unsigned) (swap_bytes_in[idx]/inf.uptime), | |
152 (unsigned) (swap_bytes_out[idx]/inf.uptime), | |
153 (unsigned) (io_pages_in[idx]/inf.uptime), | |
154 (unsigned) (io_pages_out[idx]/inf.uptime), | |
155 (unsigned) (sys_irq[idx]/inf.uptime), | |
156 (unsigned) (sys_ctxt[idx]/inf.uptime), | |
157 (unsigned) (100*cpu_user[idx]/total_jif), | |
158 (unsigned) (100*cpu_sys[idx]/total_jif), | |
159 (unsigned) (100*cpu_idle[idx]/total_jif), | |
160 (unsigned) (100*cpu_wait[idx]/total_jif)); | |
161 }else{ | |
162 total_jif = cpu_user[idx] - cpu_user[!idx] + cpu_idle[idx] - cpu_idle[!idx] + cpu_wait[idx] - cpu_wait[!idx]; | |
163 printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache, | |
164 (unsigned) ((swap_bytes_in[idx] - swap_bytes_in[!idx])/loop_delay), | |
165 (unsigned) ((swap_bytes_out[idx] - swap_bytes_out[!idx])/loop_delay), | |
166 (unsigned) ((io_pages_in[idx] - io_pages_in[!idx])/loop_delay), | |
167 (unsigned) ((io_pages_out[idx] - io_pages_out[!idx])/loop_delay), | |
168 (unsigned) ((sys_irq[idx] - sys_irq[!idx])/loop_delay), | |
169 (unsigned) ((sys_ctxt[idx] - sys_ctxt[!idx])/loop_delay), | |
170 (unsigned) (100*(cpu_user[idx] - cpu_user[!idx])/total_jif), | |
171 (unsigned) (100*(cpu_sys[idx] - cpu_sys[!idx]) /total_jif), | |
172 (unsigned) (100*(cpu_idle[idx] - cpu_idle[!idx])/total_jif), | |
173 (unsigned) (100*(cpu_wait[idx] - cpu_wait[!idx])/total_jif)); | |
174 } | |
175 | |
176 loop_num++; | |
177 if (loop_delay == 0 || (loop_max_num != 0 && loop_num >= loop_max_num)) | |
178 break; | |
179 sleep(loop_delay); | |
180 } | |
181 } |