From: albert <> Date: Sat, 31 May 2003 00:38:55 +0000 (+0000) Subject: fabian.frederick@gmx.fr vmstat code X-Git-Tag: v3.3.0~243 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=de2857aa89c584acffc65ba10760ec337d66fa49;p=procps-ng fabian.frederick@gmx.fr vmstat code --- diff --git a/proc/library.map b/proc/library.map index 32e9d84c..19669914 100644 --- a/proc/library.map +++ b/proc/library.map @@ -10,7 +10,7 @@ global: Hertz; smp_num_cpus; sprint_uptime; uptime; user_from_uid; print_uptime; loadavg; pretty_print_signals; print_given_signals; unix_print_signals; signal_name_to_number; signal_number_to_name; - meminfo; vminfo; + meminfo; vminfo; getstat; kb_active; kb_inactive; kb_main_buffers; kb_main_cached; kb_main_free; kb_main_total; kb_main_used; kb_swap_free; kb_swap_total; kb_swap_used; kb_main_shared; diff --git a/proc/sysinfo.c b/proc/sysinfo.c index 6cf936be..933cb4e8 100644 --- a/proc/sysinfo.c +++ b/proc/sysinfo.c @@ -269,6 +269,127 @@ void loadavg(double *restrict av1, double *restrict av5, double *restrict av15) SET_IF_DESIRED(av15, avg_15); } + static char buff[BUFFSIZE]; /* used in the procedures */ +/***********************************************************************/ + +static void crash(const char *filename) { + perror(filename); + exit(EXIT_FAILURE); +} + +/***********************************************************************/ + +static void getrunners(unsigned int *restrict running, unsigned int *restrict blocked) { + struct direct *ent; + DIR *proc; + + *running=0; + *blocked=0; + + if((proc=opendir("/proc"))==NULL) crash("/proc"); + + while(( ent=readdir(proc) )) { + unsigned size; + int fd; + char filename[80]; + char c; + if (!isdigit(ent->d_name[0])) continue; + sprintf(filename, "/proc/%s/stat", ent->d_name); + fd = open(filename, O_RDONLY, 0); + if (fd == -1) continue; + read(fd,buff,BUFFSIZE-1); + sscanf( + buff, + "%*d %*s %c " + "%*d %*d %*d %*d %*d %*u %*u" + " %*u %*u %*u %*d %*d %*d %*d %*d %*d %*u %*u %*d %*u %u" + /* " %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u\n" */ , + &c, + &size + ); + close(fd); + + if (c=='R') { + (*running)++; + continue; + } + if (c=='D') { + (*blocked)++; + continue; + } + } + closedir(proc); +} + +/***********************************************************************/ + +void getstat(jiff *restrict cuse, jiff *restrict cice, jiff *restrict csys, jiff *restrict cide, jiff *restrict ciow, + unsigned long *restrict pin, unsigned long *restrict pout, unsigned long *restrict s_in, unsigned long *restrict sout, + unsigned *restrict intr, unsigned *restrict ctxt, + unsigned int *restrict running, unsigned int *restrict blocked, + unsigned int *restrict btime, unsigned int *restrict processes) { + static int fd; + int need_vmstat_file = 0; + int need_proc_scan = 0; + const char* b; + buff[BUFFSIZE-1] = 0; /* ensure null termination in buffer */ + + if(fd){ + lseek(fd, 0L, SEEK_SET); + }else{ + fd = open("/proc/stat", O_RDONLY, 0); + if(fd == -1) crash("/proc/stat"); + } + read(fd,buff,BUFFSIZE-1); + *intr = 0; + *ciow = 0; /* not separated out until the 2.5.41 kernel */ + + b = strstr(buff, "cpu "); + if(b) sscanf(b, "cpu %Lu %Lu %Lu %Lu %Lu", cuse, cice, csys, cide, ciow); + + b = strstr(buff, "page "); + if(b) sscanf(b, "page %lu %lu", pin, pout); + else need_vmstat_file = 1; + + b = strstr(buff, "swap "); + if(b) sscanf(b, "swap %lu %lu", s_in, sout); + else need_vmstat_file = 1; + + b = strstr(buff, "intr "); + if(b) sscanf(b, "intr %u", intr); + + b = strstr(buff, "ctxt "); + if(b) sscanf(b, "ctxt %u", ctxt); + + b = strstr(buff, "btime "); + if(b) sscanf(b, "btime %u", btime); + + b = strstr(buff, "processes "); + if(b) sscanf(b, "processes %u", processes); + + b = strstr(buff, "procs_running "); + if(b) sscanf(b, "procs_running %u", running); + else need_proc_scan = 1; + + b = strstr(buff, "procs_blocked "); + if(b) sscanf(b, "procs_blocked %u", blocked); + else need_proc_scan = 1; + + if(need_proc_scan){ /* Linux 2.5.46 (approximately) and below */ + getrunners(running, blocked); + } + + (*running)--; // exclude vmstat itself + + if(need_vmstat_file){ /* Linux 2.5.40-bk4 and above */ + vminfo(); + *pin = vm_pgpgin; + *pout = vm_pgpgout; + *s_in = vm_pswpin; + *sout = vm_pswpout; + } +} + /***********************************************************************/ /* * Copyright 1999 by Albert Cahalan; all rights reserved. @@ -529,4 +650,4 @@ nextline: head = tail+1; } } -/*****************************************************************/ + diff --git a/proc/sysinfo.h b/proc/sysinfo.h index 0189b464..4e60b10e 100644 --- a/proc/sysinfo.h +++ b/proc/sysinfo.h @@ -1,6 +1,7 @@ #ifndef PROC_SYSINFO_H #define PROC_SYSINFO_H - +#include +#include #include "procps.h" EXTERN_C_BEGIN @@ -50,6 +51,16 @@ extern unsigned long kb_inactive; extern unsigned long kb_mapped; extern unsigned long kb_pagetables; +#define BUFFSIZE 8192 +typedef unsigned long long jiff; +extern void crash(const char *filename); +extern void getrunners(unsigned int *restrict running, unsigned int *restrict blocked); +extern void getstat(jiff *restrict cuse, jiff *restrict cice, jiff *restrict csys, jiff *restrict cide, jiff *restrict ciow, + unsigned long *restrict pin, unsigned long *restrict pout, unsigned long *restrict s_in, unsigned long *restrict sout, + unsigned *restrict intr, unsigned *restrict ctxt, + unsigned int *restrict running, unsigned int *restrict blocked, + unsigned int *restrict btime, unsigned int *restrict processes); + extern void meminfo(void); diff --git a/vmstat.8 b/vmstat.8 index f0c16774..bcf89ed1 100644 --- a/vmstat.8 +++ b/vmstat.8 @@ -15,6 +15,9 @@ vmstat \- Report virtual memory statistics .RB [ "\-s" ] .br .B vmstat +.RB [ "\-S unit"] +.br +.B vmstat .RB [ "\-V" ] .SH DESCRIPTION \fBvmstat\fP reports information about processes, memory, paging, @@ -46,6 +49,8 @@ only one report is printed with the average values since boot. is the number of updates. If no count is specified and delay is defined, \fIcount\fP defaults to infinity. .PP +The \fB-S\fP followed by k or K or m or M switches outputs between 1000, 1024, 1000000, or 1048576 bytes +.PP The \fB-V\fP switch results in displaying version information. .PP .SH FIELD DESCRIPTIONS @@ -53,25 +58,25 @@ The \fB-V\fP switch results in displaying version information. .B "Procs" .nf r: The number of processes waiting for run time. -b: The number of processes in uninterruptable sleep. +b: The number of processes in uninterruptible sleep. .fi .PP .SS .B "Memory" .nf -swpd: the amount of virtual memory used (kB). -free: the amount of idle memory (kB). -buff: the amount of memory used as buffers (kB). -cache: the amount of memory used as cache (kB). -inact: the amount of inactive memory (kB). (-a option) -active: the amount of active memory (kB). (-a option) +swpd: the amount of virtual memory used. +free: the amount of idle memory. +buff: the amount of memory used as buffers. +cache: the amount of memory used as cache. +inact: the amount of inactive memory. (-a option) +active: the amount of active memory. (-a option) .fi .PP .SS .B "Swap" .nf -si: Amount of memory swapped in from disk (kB/s). -so: Amount of memory swapped to disk (kB/s). +si: Amount of memory swapped in from disk (/s). +so: Amount of memory swapped to disk (/s). .fi .PP .SS @@ -108,6 +113,8 @@ does not count itself as a running process. All linux blocks are currently 1024 bytes. Old kernels may report blocks as 512 bytes, 2048 bytes, or 4096 bytes. .PP +Since procps 3.1.9, vmstat lets you choose units (k, K, m, M) +.PP .SH FILES .ta .nf diff --git a/vmstat.c b/vmstat.c index 189892f4..740a6d6e 100644 --- a/vmstat.c +++ b/vmstat.c @@ -1,5 +1,8 @@ // old: "Copyright 1994 by Henry Ware . Copyleft same year." // most code copyright 2002 Albert Cahalan +// 27/05/2003 (Fabian) : Add unit conversion + interface +// Export proc/stat access to libproc +// Adapt vmstat helpfile #include #include @@ -16,15 +19,11 @@ #include "proc/sysinfo.h" #include "proc/version.h" +#include "vmstat.h" -#define BUFFSIZE 8192 #define FALSE 0 #define TRUE 1 -static char buff[BUFFSIZE]; /* used in the procedures */ - -typedef unsigned long long jiff; - static int a_option; /* "-a" means "show active/inactive" */ static unsigned sleep_time = 1; @@ -42,131 +41,14 @@ static void usage(void) { fprintf(stderr," -V prints version.\n"); fprintf(stderr," -n causes the headers not to be reprinted regularly.\n"); fprintf(stderr," -a print inactive/active page stats.\n"); + fprintf(stderr," -S unit size\n"); fprintf(stderr," delay is the delay between updates in seconds. \n"); + fprintf(stderr," unit size k:1000 K:1024 m:1000000 M:1048576 (default is K)\n"); fprintf(stderr," count is the number of updates.\n"); exit(EXIT_FAILURE); } -static void crash(const char *filename) NORETURN; -static void crash(const char *filename) { - perror(filename); - exit(EXIT_FAILURE); -} - - -//////////////////////////////////////////////////////////////////////// - -static void getrunners(unsigned int *restrict running, unsigned int *restrict blocked) { - static struct direct *ent; - DIR *proc; - - *running=0; - *blocked=0; - - if((proc=opendir("/proc"))==NULL) crash("/proc"); - - while(( ent=readdir(proc) )) { - unsigned size; - int fd; - char filename[80]; - char c; - if (!isdigit(ent->d_name[0])) continue; - sprintf(filename, "/proc/%s/stat", ent->d_name); - fd = open(filename, O_RDONLY, 0); - if (fd == -1) continue; - read(fd,buff,BUFFSIZE-1); - sscanf( - buff, - "%*d %*s %c " - "%*d %*d %*d %*d %*d %*u %*u" - " %*u %*u %*u %*d %*d %*d %*d %*d %*d %*u %*u %*d %*u %u" - /* " %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u\n" */ , - &c, - &size - ); - close(fd); - - if (c=='R') { - (*running)++; - continue; - } - if (c=='D') { - (*blocked)++; - continue; - } - } - closedir(proc); -} - -static void getstat(jiff *restrict cuse, jiff *restrict cice, jiff *restrict csys, jiff *restrict cide, jiff *restrict ciow, - unsigned long *restrict pin, unsigned long *restrict pout, unsigned long *restrict s_in, unsigned long *restrict sout, - unsigned *restrict intr, unsigned *restrict ctxt, - unsigned int *restrict running, unsigned int *restrict blocked, - unsigned int *restrict btime, unsigned int *restrict processes) { - static int fd; - int need_vmstat_file = 0; - int need_proc_scan = 0; - const char* b; - buff[BUFFSIZE-1] = 0; /* ensure null termination in buffer */ - - if(fd){ - lseek(fd, 0L, SEEK_SET); - }else{ - fd = open("/proc/stat", O_RDONLY, 0); - if(fd == -1) crash("/proc/stat"); - } - read(fd,buff,BUFFSIZE-1); - *intr = 0; - *ciow = 0; /* not separated out until the 2.5.41 kernel */ - - b = strstr(buff, "cpu "); - if(b) sscanf(b, "cpu %Lu %Lu %Lu %Lu %Lu", cuse, cice, csys, cide, ciow); - - b = strstr(buff, "page "); - if(b) sscanf(b, "page %lu %lu", pin, pout); - else need_vmstat_file = 1; - - b = strstr(buff, "swap "); - if(b) sscanf(b, "swap %lu %lu", s_in, sout); - else need_vmstat_file = 1; - - b = strstr(buff, "intr "); - if(b) sscanf(b, "intr %u", intr); - - b = strstr(buff, "ctxt "); - if(b) sscanf(b, "ctxt %u", ctxt); - - b = strstr(buff, "btime "); - if(b) sscanf(b, "btime %u", btime); - - b = strstr(buff, "processes "); - if(b) sscanf(b, "processes %u", processes); - - b = strstr(buff, "procs_running "); - if(b) sscanf(b, "procs_running %u", running); - else need_proc_scan = 1; - - b = strstr(buff, "procs_blocked "); - if(b) sscanf(b, "procs_blocked %u", blocked); - else need_proc_scan = 1; - - if(need_proc_scan){ /* Linux 2.5.46 (approximately) and below */ - getrunners(running, blocked); - } - - (*running)--; // exclude vmstat itself - - if(need_vmstat_file){ /* Linux 2.5.40-bk4 and above */ - vminfo(); - *pin = vm_pgpgin; - *pout = vm_pgpgout; - *s_in = vm_pswpin; - *sout = vm_pswpout; - } -} - - -////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// #if 0 // produce: " 6 ", "123 ", "123k ", etc. @@ -248,6 +130,17 @@ static void new_header(void){ ); } +//////////////////////////////////////////////////////////////////////////// + +unsigned long unitConvert(unsigned int kbsize) +{ + float cvSize; + cvSize=(float)kbsize/dataUnit*1024; + return ((unsigned long) cvSize); +} + +//////////////////////////////////////////////////////////////////////////// + static void new_format(void) { const char format[]="%2u %2u %6lu %6lu %6lu %6lu %4u %4u %5u %5u %4u %5u %2u %2u %2u %2u\n"; unsigned int tog=0; /* toggle switch for cleaner code */ @@ -266,11 +159,13 @@ static void new_format(void) { new_header(); meminfo(); + getstat(cpu_use,cpu_nic,cpu_sys,cpu_idl,cpu_iow, pgpgin,pgpgout,pswpin,pswpout, intr,ctxt, &running,&blocked, &dummy_1, &dummy_2); + duse= *cpu_use + *cpu_nic; dsys= *cpu_sys; didl= *cpu_idl; @@ -279,11 +174,11 @@ static void new_format(void) { divo2= Div/2UL; printf(format, running, blocked, - kb_swap_used, kb_main_free, - a_option?kb_inactive:kb_main_buffers, - a_option?kb_active:kb_main_cached, - (unsigned)( (*pswpin * kb_per_page * hz + divo2) / Div ), - (unsigned)( (*pswpout * kb_per_page * hz + divo2) / Div ), + unitConvert(kb_swap_used), unitConvert(kb_main_free), + unitConvert(a_option?kb_inactive:kb_main_buffers), + unitConvert(a_option?kb_active:kb_main_cached), + (unsigned)( (*pswpin * unitConvert(kb_per_page) * hz + divo2) / Div ), + (unsigned)( (*pswpout * unitConvert(kb_per_page) * hz + divo2) / Div ), (unsigned)( (*pgpgin * hz + divo2) / Div ), (unsigned)( (*pgpgout * hz + divo2) / Div ), (unsigned)( (*intr * hz + divo2) / Div ), @@ -300,11 +195,13 @@ static void new_format(void) { tog= !tog; meminfo(); + getstat(cpu_use+tog,cpu_nic+tog,cpu_sys+tog,cpu_idl+tog,cpu_iow+tog, pgpgin+tog,pgpgout+tog,pswpin+tog,pswpout+tog, intr+tog,ctxt+tog, &running,&blocked, &dummy_1,&dummy_2); + duse= cpu_use[tog]-cpu_use[!tog] + cpu_nic[tog]-cpu_nic[!tog]; dsys= cpu_sys[tog]-cpu_sys[!tog]; didl= cpu_idl[tog]-cpu_idl[!tog]; @@ -324,25 +221,24 @@ static void new_format(void) { divo2= Div/2UL; printf(format, running, blocked, - kb_swap_used,kb_main_free, - a_option?kb_inactive:kb_main_buffers, - a_option?kb_active:kb_main_cached, - (unsigned)( ( (pswpin [tog] - pswpin [!tog])*kb_per_page+sleep_half )/sleep_time ), - (unsigned)( ( (pswpout[tog] - pswpout[!tog])*kb_per_page+sleep_half )/sleep_time ), - (unsigned)( ( pgpgin [tog] - pgpgin [!tog] +sleep_half )/sleep_time ), - (unsigned)( ( pgpgout[tog] - pgpgout[!tog] +sleep_half )/sleep_time ), - (unsigned)( ( intr [tog] - intr [!tog] +sleep_half )/sleep_time ), - (unsigned)( ( ctxt [tog] - ctxt [!tog] +sleep_half )/sleep_time ), - (unsigned)( (100*duse+divo2)/Div ), - (unsigned)( (100*dsys+divo2)/Div ), - (unsigned)( (100*didl+divo2)/Div ), - (unsigned)( (100*diow+divo2)/Div ) + unitConvert(kb_swap_used),unitConvert(kb_main_free), + unitConvert(a_option?kb_inactive:kb_main_buffers), + unitConvert(a_option?kb_active:kb_main_cached), + (unsigned)( ( (pswpin [tog] - pswpin [!tog])*unitConvert(kb_per_page)+sleep_half )/sleep_time ), /*si*/ + (unsigned)( ( (pswpout[tog] - pswpout[!tog])*unitConvert(kb_per_page)+sleep_half )/sleep_time ), /*so*/ + (unsigned)( ( pgpgin [tog] - pgpgin [!tog] +sleep_half )/sleep_time ), /*bi*/ + (unsigned)( ( pgpgout[tog] - pgpgout[!tog] +sleep_half )/sleep_time ), /*bo*/ + (unsigned)( ( intr [tog] - intr [!tog] +sleep_half )/sleep_time ), /*in*/ + (unsigned)( ( ctxt [tog] - ctxt [!tog] +sleep_half )/sleep_time ), /*cs*/ + (unsigned)( (100*duse+divo2)/Div ), /*us*/ + (unsigned)( (100*dsys+divo2)/Div ), /*sy*/ + (unsigned)( (100*didl+divo2)/Div ), /*id*/ + (unsigned)( (100*diow+divo2)/Div ) /*wa*/ ); } } - -////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// static void sum_format(void) { unsigned int running, blocked, btime, processes; @@ -351,21 +247,23 @@ static void sum_format(void) { unsigned int intr, ctxt; meminfo(); + getstat(&cpu_use, &cpu_nic, &cpu_sys, &cpu_idl, &cpu_iow, &pgpgin, &pgpgout, &pswpin, &pswpout, &intr, &ctxt, &running, &blocked, &btime, &processes); - printf("%13lu kB total memory\n", kb_main_total); - printf("%13lu kB used memory\n", kb_main_used); - printf("%13lu kB active memory\n", kb_active); - printf("%13lu kB inactive memory\n", kb_inactive); - printf("%13lu kB free memory\n", kb_main_free); - printf("%13lu kB buffer memory\n", kb_main_buffers); - printf("%13lu kB swap cache\n", kb_main_cached); - printf("%13lu kB total swap\n", kb_swap_total); - printf("%13lu kB used swap\n", kb_swap_used); - printf("%13lu kB free swap\n", kb_swap_free); + + printf("%13lu %s total memory\n", unitConvert(kb_main_total),szDataUnit); + printf("%13lu %s used memory\n", unitConvert(kb_main_used),szDataUnit); + printf("%13lu %s active memory\n", unitConvert(kb_active),szDataUnit); + printf("%13lu %s inactive memory\n", unitConvert(kb_inactive),szDataUnit); + printf("%13lu %s free memory\n", unitConvert(kb_main_free),szDataUnit); + printf("%13lu %s buffer memory\n", unitConvert(kb_main_buffers),szDataUnit); + printf("%13lu %s swap cache\n", unitConvert(kb_main_cached),szDataUnit); + printf("%13lu %s total swap\n", unitConvert(kb_swap_total),szDataUnit); + printf("%13lu %s used swap\n", unitConvert(kb_swap_used),szDataUnit); + printf("%13lu %s free swap\n", unitConvert(kb_swap_free),szDataUnit); printf("%13Lu non-nice user cpu ticks\n", cpu_use); printf("%13Lu nice user cpu ticks\n", cpu_nic); printf("%13Lu system cpu ticks\n", cpu_sys); @@ -380,7 +278,6 @@ static void sum_format(void) { printf("%13u boot time\n", btime); printf("%13u forks\n", processes); } - static void fork_format(void) { unsigned int running, blocked, btime, processes; jiff cpu_use, cpu_nic, cpu_sys, cpu_idl, cpu_iow; @@ -392,6 +289,7 @@ static void fork_format(void) { &intr, &ctxt, &running, &blocked, &btime, &processes); + printf("%13u forks\n", processes); } @@ -412,6 +310,7 @@ int main(int argc, char *argv[]) { for (argv++;*argv;argv++) { if ('-' ==(**argv)) { switch (*(++(*argv))) { + case 'V': display_version(); exit(0); @@ -427,6 +326,22 @@ int main(int argc, char *argv[]) { /* print only one header */ moreheaders=FALSE; break; + case 'S': + if (argv[1]){ + ++argv; + if (!strcmp(*argv, "k")) dataUnit=UNIT_k; + else if (!strcmp(*argv, "K")) dataUnit=UNIT_K; + else if (!strcmp(*argv, "m")) dataUnit=UNIT_m; + else if (!strcmp(*argv, "M")) dataUnit=UNIT_M; + else {fprintf(stderr, "-S requires k, K, m or M (default is kb)\n"); + exit(EXIT_FAILURE); + } + strcpy(szDataUnit, *argv); + }else {fprintf(stderr, "-S requires an argument\n"); + exit(EXIT_FAILURE); + } + break; + case 's': // FIXME: check for conflicting args sum_format(); diff --git a/vmstat.h b/vmstat.h new file mode 100644 index 00000000..8e7f1ce0 --- /dev/null +++ b/vmstat.h @@ -0,0 +1,27 @@ +/* vmstat.h - Header file: memory usage */ +/* + * Copyright (c) 2003, by: Fabian Frederick + * All rights reserved. fabian.frederick@gmx.fr + * + * + * This file may be used subject to the terms and conditions of the + * GNU Library General Public License Version 2, or any later version + * at your option, as published by the Free Software Foundation. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * + */ + +#ifndef _IVMstat +#define _IVMstat +unsigned long dataUnit=1024; +char szDataUnit [16]; +#define UNIT_k 1000 +#define UNIT_K 1024 +#define UNIT_m 1000000 +#define UNIT_M 1048576 + +#endif /* _IVMstat */