comparison toys/other/vmstat.c @ 653:2986aa63a021

Move commands into "posix", "lsb", and "other" menus/directories.
author Rob Landley <rob@landley.net>
date Sat, 25 Aug 2012 14:25:22 -0500
parents toys/vmstat.c@4d802d438983
children 6df4ccc0acbe
comparison
equal deleted inserted replaced
652:2d7c56913fda 653:2986aa63a021
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 size_t s = xread(fd, toybuf, sizeof(toybuf)-1);
32 toybuf[s] = 0;
33 if ( s == sizeof(toybuf)-1)
34 error_exit("/proc/stat is too large");
35
36 off = strstr(toybuf, "cpu ");
37 // Ignoring steal and guest fields for now.
38 if (off) sscanf(off, "cpu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64 \
39 " %"PRIu64" %"PRIu64" %"PRIu64, &c_user, &c_nice, &c_sys, cpu_idle,
40 cpu_wait, &c_irq, &c_sirq);
41 *cpu_user = c_user + c_nice;
42 *cpu_sys = c_sys + c_irq + c_sirq;
43 off = strstr(toybuf, "intr");
44 if (off) sscanf(off, "intr %"PRIu64, sys_irq);
45
46 off = strstr(toybuf, "ctxt");
47 if (off) sscanf(off, "ctxt %"PRIu64, sys_ctxt);
48
49 off = strstr(toybuf, "procs_running");
50 if (off) sscanf(off, "procs_running %u", proc_running);
51 (*proc_running)--; // look, i'm invisible.
52
53 off = strstr(toybuf, "procs_blocked");
54 if (off) sscanf(off, "procs_blocked %u", proc_blocked);
55
56 close(fd);
57 }
58
59 void read_proc_meminfo(unsigned long * mem_swapped, unsigned long * mem_free,
60 unsigned long * mem_buff, unsigned long * mem_cache)
61 {
62 char * off;
63 unsigned long swap_total, swap_free;
64 int fd = xopen("/proc/meminfo", O_RDONLY);
65 size_t s = xread(fd, toybuf, sizeof(toybuf)-1);
66 toybuf[s] = 0;
67 if ( s == sizeof(toybuf)-1)
68 error_exit("/proc/meminfo is too large");
69
70 off = strstr(toybuf, "MemFree");
71 if (off) sscanf(off, "MemFree: %lu kB", mem_free);
72
73 off = strstr(toybuf, "Buffers");
74 if (off) sscanf(off, "Buffers: %lu kB", mem_buff);
75
76 off = strstr(toybuf, "Cached");
77 if (off) sscanf(off, "Cached: %lu kB", mem_cache);
78
79 off = strstr(toybuf, "SwapFree");
80 if (off) sscanf(off, "SwapFree: %lu kB", &swap_free);
81
82 off = strstr(toybuf, "SwapTotal");
83 if (off) sscanf(off, "SwapTotal: %lu kB", &swap_total);
84 *mem_swapped = swap_total - swap_free;
85
86 close(fd);
87 }
88
89 void read_proc_vmstat(unsigned long * io_pages_in, unsigned long * io_pages_out,
90 unsigned long * swap_bytes_in, unsigned long * swap_bytes_out)
91 {
92 char * off;
93 unsigned long s_pages_in, s_pages_out;
94 unsigned long pagesize_kb = sysconf(_SC_PAGESIZE) / 1024L;
95 int fd = xopen("/proc/vmstat", O_RDONLY);
96 size_t s = xread(fd, toybuf, sizeof(toybuf)-1);
97 toybuf[s] = 0;
98 if ( s == sizeof(toybuf)-1)
99 error_exit("/proc/vmstat is too large");
100
101 off = strstr(toybuf, "pgpgin");
102 if (off) sscanf(off, "pgpgin %lu", io_pages_in);
103
104 off = strstr(toybuf, "pgpgout");
105 if (off) sscanf(off, "pgpgout %lu", io_pages_out);
106
107 off = strstr(toybuf, "pswpin");
108 if (off) sscanf(off, "pswpin %lu", &s_pages_in);
109 *swap_bytes_in = s_pages_in * pagesize_kb;
110
111 off = strstr(toybuf, "pswpout");
112 if (off) sscanf(off, "pswpout %lu", &s_pages_out);
113 *swap_bytes_out = s_pages_out * pagesize_kb;
114
115 close(fd);
116 }
117
118 void vmstat_main(void)
119 {
120 const char fmt[] = "%2u %2u %6lu %6lu %6lu %6lu %4u %4u %5u %5u %4u %4u %2u %2u %2u %2u\n";
121 unsigned int loop_num = 0, loop_max_num = 0, loop_delay = 0;
122 unsigned int running = 0, blocked = 0;
123 unsigned long mem_swap = 0, mem_free = 0, mem_buff = 0, mem_cache = 0;
124 unsigned long io_pages_in[2], io_pages_out[2], swap_bytes_in[2], swap_bytes_out[2];
125 uint64_t sys_irq[2], sys_ctxt[2], cpu_user[2], cpu_sys[2], cpu_idle[2], cpu_wait[2];
126 int first_run = 1;
127 int no_header = toys.optflags & 0x1;
128 unsigned num_rows = 22;
129
130 if (toys.optc >= 1)
131 loop_delay = atoi(toys.optargs[0]);
132 if (toys.optc >= 2)
133 loop_max_num = atoi(toys.optargs[1]);
134
135 if (loop_max_num < 0 || loop_delay < 0)
136 error_exit("Invalid arguments");
137
138 while(1) {
139 uint64_t total_jif;
140 int idx = loop_num%2;
141
142 if(first_run || (!(loop_num % num_rows) && !no_header)) {
143 unsigned rows = 0, cols = 0;
144 terminal_size(&cols, &rows);
145 num_rows = (rows > 3)? rows - 3 : 22;
146 printf("procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----\n");
147 printf(" r b swpd free buff cache si so bi bo in cs us sy id wa\n");
148 }
149
150 read_proc_stat(&running, &blocked, &sys_irq[idx], &sys_ctxt[idx], &cpu_user[idx],
151 &cpu_sys[idx], &cpu_idle[idx], &cpu_wait[idx]);
152 read_proc_meminfo(&mem_swap, &mem_free, &mem_buff, &mem_cache);
153 read_proc_vmstat(&io_pages_in[idx], &io_pages_out[idx], &swap_bytes_in[idx], &swap_bytes_out[idx]);
154
155 if (first_run) {
156 struct sysinfo inf;
157 sysinfo(&inf);
158 first_run = 0;
159 total_jif = cpu_user[idx] + cpu_idle[idx] + cpu_wait[idx];
160 printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache,
161 (unsigned) (swap_bytes_in[idx]/inf.uptime),
162 (unsigned) (swap_bytes_out[idx]/inf.uptime),
163 (unsigned) (io_pages_in[idx]/inf.uptime),
164 (unsigned) (io_pages_out[idx]/inf.uptime),
165 (unsigned) (sys_irq[idx]/inf.uptime),
166 (unsigned) (sys_ctxt[idx]/inf.uptime),
167 (unsigned) (100*cpu_user[idx]/total_jif),
168 (unsigned) (100*cpu_sys[idx]/total_jif),
169 (unsigned) (100*cpu_idle[idx]/total_jif),
170 (unsigned) (100*cpu_wait[idx]/total_jif));
171 }else{
172 total_jif = cpu_user[idx] - cpu_user[!idx] + cpu_idle[idx] - cpu_idle[!idx] + cpu_wait[idx] - cpu_wait[!idx];
173 printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache,
174 (unsigned) ((swap_bytes_in[idx] - swap_bytes_in[!idx])/loop_delay),
175 (unsigned) ((swap_bytes_out[idx] - swap_bytes_out[!idx])/loop_delay),
176 (unsigned) ((io_pages_in[idx] - io_pages_in[!idx])/loop_delay),
177 (unsigned) ((io_pages_out[idx] - io_pages_out[!idx])/loop_delay),
178 (unsigned) ((sys_irq[idx] - sys_irq[!idx])/loop_delay),
179 (unsigned) ((sys_ctxt[idx] - sys_ctxt[!idx])/loop_delay),
180 (unsigned) (100*(cpu_user[idx] - cpu_user[!idx])/total_jif),
181 (unsigned) (100*(cpu_sys[idx] - cpu_sys[!idx]) /total_jif),
182 (unsigned) (100*(cpu_idle[idx] - cpu_idle[!idx])/total_jif),
183 (unsigned) (100*(cpu_wait[idx] - cpu_wait[!idx])/total_jif));
184 }
185
186 loop_num++;
187 if (loop_delay == 0 || (loop_max_num != 0 && loop_num >= loop_max_num))
188 break;
189 sleep(loop_delay);
190 }
191 }