diff options
| author | Elie De Brauwer <eliedebrauwer@gmail.com> | 2012-04-09 13:31:44 +0200 | 
|---|---|---|
| committer | Elie De Brauwer <eliedebrauwer@gmail.com> | 2012-04-09 13:31:44 +0200 | 
| commit | 0392c177d0f21a8916e4a6835454411d15fe5a9c (patch) | |
| tree | 0a1f5d1cd27602cbf15193255ca661e7f7deca95 | |
| parent | 8ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97 (diff) | |
| download | toybox-0392c177d0f21a8916e4a6835454411d15fe5a9c.tar.gz | |
Adding vmstat
| -rw-r--r-- | toys/vmstat.c | 181 | 
1 files changed, 181 insertions, 0 deletions
| diff --git a/toys/vmstat.c b/toys/vmstat.c new file mode 100644 index 00000000..12669458 --- /dev/null +++ b/toys/vmstat.c @@ -0,0 +1,181 @@ +/* vi: set sw=4 ts=4: + * + * vmstat.c - Report virtual memory statistics. + * + * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com> + * + * Not in SUSv4. + +USE_VMSTAT(NEWTOY(vmstat, ">2n", TOYFLAG_BIN)) + +config VMSTAT +	bool "vmstat" +	default y +	help +	  usage: vmstat [-n] [delay [count]] +	  -n Display the header only once +	  delay The delay between updates in seconds, when not specified +	        the average since boot is displayed. +	  count Number of updates to display, the default is inifinite. +*/ + +#include "toys.h" + +void read_proc_stat(unsigned int * proc_running, unsigned int * proc_blocked,  +               uint64_t * sys_irq, uint64_t * sys_ctxt, +               uint64_t * cpu_user, uint64_t * cpu_sys, uint64_t * cpu_idle, uint64_t * cpu_wait) +{ +    char * off; +    uint64_t c_user, c_nice, c_sys, c_irq, c_sirq; +    int fd = xopen("/proc/stat", O_RDONLY); +    if (fdlength(fd) > sizeof(toybuf)) +        error_exit("/proc/stat is too large"); +    xread(fd, toybuf, sizeof(toybuf)); + +    off = strstr(toybuf, "cpu "); +    // Ignoring steal and guest fields for now. +    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); +    *cpu_user = c_user + c_nice; +    *cpu_sys = c_sys + c_irq + c_sirq; +    off = strstr(toybuf, "intr"); +    if (off) sscanf(off, "intr %Lu", sys_irq); + +    off = strstr(toybuf, "ctxt"); +    if (off) sscanf(off, "ctxt %Lu", sys_ctxt); + +    off = strstr(toybuf, "procs_running"); +    if (off) sscanf(off, "procs_running %u", proc_running); +    (*proc_running)--; // look, i'm invisible. +     +    off = strstr(toybuf, "procs_blocked"); +    if (off) sscanf(off, "procs_blocked %u", proc_blocked); + +    close(fd); +} + +void read_proc_meminfo(unsigned long * mem_swapped, unsigned long * mem_free,  +                       unsigned long * mem_buff, unsigned long * mem_cache) +{ +    char * off; +    unsigned long swap_total, swap_free; +    int fd = xopen("/proc/meminfo", O_RDONLY);     +    if (fdlength(fd) > sizeof(toybuf)) +        error_exit("/proc/meminfo is too large"); +    xread(fd, toybuf, sizeof(toybuf)); + +    off = strstr(toybuf, "MemFree"); +    if (off) sscanf(off, "MemFree: %lu kB", mem_free);  + +    off = strstr(toybuf, "Buffers"); +    if (off) sscanf(off, "Buffers: %lu kB", mem_buff); + +    off = strstr(toybuf, "Cached"); +    if (off) sscanf(off, "Cached: %lu kB", mem_cache); + +    off = strstr(toybuf, "SwapFree"); +    if (off) sscanf(off, "SwapFree: %lu kB", &swap_free);  + +    off = strstr(toybuf, "SwapTotal"); +    if (off) sscanf(off, "SwapTotal: %lu kB", &swap_total); +    *mem_swapped = swap_total - swap_free; + +    close(fd); +} + +void read_proc_vmstat(unsigned long * io_pages_in, unsigned long * io_pages_out, unsigned long * swap_bytes_in, unsigned long * swap_bytes_out) +{ +    char * off; +    unsigned long s_pages_in, s_pages_out; +    unsigned long pagesize_kb = sysconf(_SC_PAGESIZE) / 1024L; +    int fd = xopen("/proc/vmstat", O_RDONLY); +    if (fdlength(fd) > sizeof(toybuf)) +        error_exit("/proc/vmstat is too large"); +    xread(fd, toybuf, sizeof(toybuf)); + +    off = strstr(toybuf, "pgpgin"); +    if (off) sscanf(off, "pgpgin %lu", io_pages_in); + +    off = strstr(toybuf, "pgpgout"); +    if (off) sscanf(off, "pgpgout %lu", io_pages_out); + +    off = strstr(toybuf, "pswpin"); +    if (off) sscanf(off, "pswpin %lu", &s_pages_in); +    *swap_bytes_in = s_pages_in * pagesize_kb; + +    off = strstr(toybuf, "pswpout"); +    if (off) sscanf(off, "pswpout %lu", &s_pages_out); +    *swap_bytes_out = s_pages_out * pagesize_kb; + +    close(fd); +} + +void vmstat_main(void) +{	 +    const char fmt[] = "%2u %2u %6lu %6lu %6lu %6lu %4u %4u %5u %5u %4u %4u %2u %2u %2u %2u\n"; +    unsigned int loop_num = 0, loop_max_num = 0, loop_delay = 0; +    unsigned int running = 0, blocked = 0; +    unsigned long mem_swap = 0, mem_free = 0, mem_buff = 0, mem_cache = 0; +    unsigned long io_pages_in[2], io_pages_out[2], swap_bytes_in[2], swap_bytes_out[2]; +    uint64_t sys_irq[2], sys_ctxt[2], cpu_user[2], cpu_sys[2], cpu_idle[2], cpu_wait[2]; +    int first_run = 1; +    int no_header = toys.optflags & 0x1; + +    if (toys.optc >= 1) +        loop_delay = atoi(toys.optargs[0]); +    if (toys.optc >= 2) +        loop_max_num = atoi(toys.optargs[1]); + +    if (loop_max_num < 0 || loop_delay < 0) +        error_exit("Invalid arguments"); + +    while(1) { +        uint64_t total_jif; +        int idx = loop_num%2; + +        if(first_run || (!(loop_num % 22) && !no_header)) { +            printf("procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----\n"); +            printf(" r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa\n"); +        } + +        read_proc_stat(&running, &blocked, &sys_irq[idx], &sys_ctxt[idx], &cpu_user[idx], +                       &cpu_sys[idx], &cpu_idle[idx], &cpu_wait[idx]); +        read_proc_meminfo(&mem_swap, &mem_free, &mem_buff, &mem_cache); +        read_proc_vmstat(&io_pages_in[idx], &io_pages_out[idx], &swap_bytes_in[idx], &swap_bytes_out[idx]); + +        if (first_run) { +            struct sysinfo inf; +            sysinfo(&inf); +            first_run = 0; +            total_jif = cpu_user[idx] + cpu_idle[idx] + cpu_wait[idx]; +            printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache, +                   (unsigned) (swap_bytes_in[idx]/inf.uptime), +                   (unsigned) (swap_bytes_out[idx]/inf.uptime), +                   (unsigned) (io_pages_in[idx]/inf.uptime), +                   (unsigned) (io_pages_out[idx]/inf.uptime), +                   (unsigned) (sys_irq[idx]/inf.uptime), +                   (unsigned) (sys_ctxt[idx]/inf.uptime), +                   (unsigned) (100*cpu_user[idx]/total_jif), +                   (unsigned) (100*cpu_sys[idx]/total_jif), +                   (unsigned) (100*cpu_idle[idx]/total_jif), +                   (unsigned) (100*cpu_wait[idx]/total_jif)); +        }else{ +            total_jif = cpu_user[idx] - cpu_user[!idx] + cpu_idle[idx] - cpu_idle[!idx] + cpu_wait[idx] - cpu_wait[!idx]; +            printf(fmt, running, blocked, mem_swap, mem_free, mem_buff, mem_cache, +                   (unsigned) ((swap_bytes_in[idx] - swap_bytes_in[!idx])/loop_delay), +                   (unsigned) ((swap_bytes_out[idx] - swap_bytes_out[!idx])/loop_delay), +                   (unsigned) ((io_pages_in[idx] - io_pages_in[!idx])/loop_delay), +                   (unsigned) ((io_pages_out[idx] - io_pages_out[!idx])/loop_delay), +                   (unsigned) ((sys_irq[idx] - sys_irq[!idx])/loop_delay), +                   (unsigned) ((sys_ctxt[idx] - sys_ctxt[!idx])/loop_delay), +                   (unsigned) (100*(cpu_user[idx] - cpu_user[!idx])/total_jif), +                   (unsigned) (100*(cpu_sys[idx]  - cpu_sys[!idx]) /total_jif), +                   (unsigned) (100*(cpu_idle[idx] - cpu_idle[!idx])/total_jif), +                   (unsigned) (100*(cpu_wait[idx] - cpu_wait[!idx])/total_jif)); +        } +         +        loop_num++; +        if (loop_delay == 0 || (loop_max_num != 0 && loop_num >= loop_max_num)) +            break; +        sleep(loop_delay); +    } +} | 
