home *** CD-ROM | disk | FTP | other *** search
- #define VERSION Version: 0.06, last modified 2 August 94: ALPHA
- #define PROGNAME "vmstat"
- /* Copyright 1994 by Henry Ware <al172@yfn.ysu.edu>. Copyleft same year. */
- /* This attempts to display virtual memory statistics.
-
- vmstat should not run as root.
- */
- /* TODO etc.
- * Count the system calls. How? I don't even know where to start.
- * add more items- aim at Posix 1003.2 (1003.7?) compliance, if relevant (I.
- don't think it is, but let me know.)
- * sometimes d(inter)<d(ticks)!! This is not possible: inter is a sum of
- positive numbers including ticks. But it happens. This doesn't seem to
- affect things much, however.
- * It would be interesting to see when the buffers avert a block io:
- Like SysV4's "sar -b"... it might fit better here, with Linux's variable
- buffer size.
- * Ideally, blocks in & out would be counted in 1k increments, rather than
- by block: this only makes a difference for CDs and is a problematic fix.
- */
- /* PROCPS
- The procps suite is maintained as a suite by Charles Blake
- <cblake@sdcc3.UCSD.EDU>.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <fcntl.h>
- #include <assert.h>
- #include <sys/types.h>
- #include <sys/dir.h>
- #include <linux/dirent.h>
- #include <limits.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
-
- #define NDEBUG !DEBUG
-
- #define BUFFSIZE 1024
- #define FALSE 0
- #define TRUE 1
-
- int main(int, char **);
- void usage(void);
- void crash(char *);
- int winhi(void);
- void showheader(void);
- void getstat(unsigned *, unsigned *, unsigned *, unsigned long *,
- unsigned *, unsigned *, unsigned *, unsigned *,
- unsigned *, unsigned *, unsigned *);
- void getmeminfo(unsigned *, unsigned *, unsigned *);
- void getrunners(unsigned *, unsigned *, unsigned *);
- static char buff[BUFFSIZE]; /* used in the procedures */
-
- /***************************************************************
- Main
- ***************************************************************/
-
- int main(int argc, char *argv[]) {
-
- const char format[]="%2u %1u %1u %5u %5u %5u %3u %3u %4u %4u %4u %4u %3u %3u %3u\n";
- unsigned int height=22; /* window height, reset later if needed. */
- unsigned long int args[2]={0,0};
- unsigned int moreheaders=TRUE;
- unsigned int tog=0; /* toggle switch for cleaner code */
- unsigned int i,hz;
- unsigned int running,blocked,swapped;
- unsigned int cpu_use[2], cpu_nic[2], cpu_sys[2];
- unsigned int duse,dsys,didl,div,divo2;
- unsigned int memfree,membuff,swapused;
- unsigned long cpu_idl[2];
- unsigned int pgpgin[2], pgpgout[2], pswpin[2], pswpout[2];
- unsigned int inter[2],ticks[2],ctxt[2];
- unsigned int per=0, pero2;
- unsigned long num=0;
-
- argc=0; /* redefined as number of integer arguments */
- for (argv++;*argv;argv++) {
- if ('-' ==(**argv)) {
- if (*(++(*argv))=='n') {
- /* print only one header */
- moreheaders=FALSE;
- }
- else {
- /* no other aguments defined yet. */
- usage();
- }
- }
- else {
- if (!sscanf(*argv,"%lu",args+argc++)) usage();
- }
- }
- switch (argc) {
- case 0: /* no numeric args */
- per=1;
- num=0;
- break;
- case 1:
- per=(unsigned) args[0];
- num=ULONG_MAX;
- break;
- case 2:
- per=(unsigned) args[0];
- num=args[1];
- break;
- default :
- usage();
- break;
- }
-
- if (moreheaders) {
- int tmp=winhi()-3;
- height=((tmp>0)?tmp:22);
- }
-
- pero2=(per/2);
- showheader();
- getrunners(&running,&blocked,&swapped);
- getmeminfo(&memfree,&membuff,&swapused);
- getstat(cpu_use,cpu_nic,cpu_sys,cpu_idl,
- pgpgin,pgpgout,pswpin,pswpout,
- inter,ticks,ctxt);
- duse= *(cpu_use)+ *(cpu_nic);
- dsys= *(cpu_sys);
- didl= (*(cpu_idl))%UINT_MAX;
- div= (duse+dsys+didl);
- hz=sysconf(_SC_CLK_TCK); /* get ticks/s from system */
- divo2= div/2;
- printf(format,
- running,blocked,swapped,
- swapused,memfree,membuff,
- (*(pswpin)*4*hz+divo2)/div,
- (*(pswpout)*4*hz+divo2)/div,
- (*(pgpgin)*hz+divo2)/div,
- (*(pgpgout)*hz+divo2)/div,
- (*(inter)*hz+divo2)/div,
- (*(ctxt)*hz+divo2)/div,
- (100*duse+divo2)/div,(100*dsys+divo2)/div,(100*didl+divo2)/div);
-
- for(i=1;i<num;i++) { /* \\\\\\\\\\\\\\\\\\\\ main loop ////////////////// */
- sleep(per);
- if (moreheaders && ((i%height)==0)) showheader();
- tog= !tog;
- getrunners(&running,&blocked,&swapped);
- getmeminfo(&memfree,&membuff,&swapused);
- getstat(cpu_use+tog,cpu_nic+tog,cpu_sys+tog,cpu_idl+tog,
- pgpgin+tog,pgpgout+tog,pswpin+tog,pswpout+tog,
- inter+tog,ticks+tog,ctxt+tog);
- 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))%UINT_MAX;
- div= (duse+dsys+didl);
- divo2= div/2;
- printf(format,
- running,blocked,swapped,
- swapused,memfree,membuff,
- (((*(pswpin+tog)-*(pswpin+(!tog)))*4+pero2)/per),
- ((*(pswpout+tog)-*(pswpout+(!tog)))*4+pero2)/per,
- (*(pgpgin+tog)-*(pgpgin+(!tog))+pero2)/per,
- (*(pgpgout+tog)-*(pgpgout+(!tog))+pero2)/per,
- (*(inter+tog)-*(inter+(!tog))+pero2)/per,
- (*(ctxt+tog)-*(ctxt+(!tog))+pero2)/per,
- (100*duse+divo2)/div,(100*dsys+divo2)/div,(100*didl+divo2)/div);
- }
- exit(EXIT_SUCCESS);
- }
-
- /**************************** others ***********************************/
-
- void usage(void) {
- fprintf(stderr,"usage: %s [-n] [delay [count]]\n",PROGNAME);
- fprintf(stderr," -n causes the headers not to be reprinted regularly.\n");
- fprintf(stderr," delay is the delay between updates in seconds. \n");
- fprintf(stderr," count is the number of updates.\n");
- exit(EXIT_FAILURE);
- }
-
- void crash(char *filename) {
- perror(filename);
- exit(EXIT_FAILURE);
- }
-
- int winhi(void) {
- struct winsize win;
- int rows = 24;
-
- if (ioctl(1, TIOCGWINSZ, &win) != -1 && win.ws_row > 0)
- rows = win.ws_row;
-
- return rows;
- }
-
-
- void showheader(void){
- printf("%6s%18s%8s%10s%10s%12s\n",
- "procs","memory","swap","io","system","cpu");
- printf(" %1s %1s %1s %5s %5s %5s %3s %3s %4s %4s %4s %4s %3s %3s %3s\n",
- "r","b","w","swpd","free","buff","si","so","bi","bo",
- "in","cs","us","sy","id");
- }
-
- void getstat(unsigned *cuse, unsigned *cice, unsigned *csys, unsigned long *cide,
- unsigned *pin, unsigned *pout, unsigned *sin, unsigned *sout,
- unsigned *itot, unsigned *i1, unsigned *ct) {
- static int stat;
-
- if ((stat=open("/proc/stat", O_RDONLY, 0)) != -1) {
- read(stat,buff,BUFFSIZE-1);
- close(stat);
- sscanf(buff,
- "cpu %u %u %u %lu disk %*u %*u %*u %*u page %u %u swap %u %u intr %u %u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u ctxt %u",
- cuse, cice, csys, cide,
- pin, pout, sin, sout, itot, i1, ct);
- assert(*itot>*i1);
- }
- else {
- crash("/proc/stat");
- }
- }
-
- void getmeminfo(unsigned *memfree, unsigned *membuff,
- unsigned *swapused) {
- static int mem;
-
- if ((mem = open("/proc/meminfo", O_RDONLY, 0)) != -1) {
- read(mem,buff,BUFFSIZE-1);
- close(mem);
- sscanf(buff, "%*s %*s %*s %*s %*s %*s %*u %*u %u %*u %u %*s %*u %u %*u",
- memfree,membuff,swapused);
- *memfree /= 1024; /* bytes to k of course. */
- *membuff /= 1024;
- *swapused /= 1024;
- }
- else {
- crash("/proc/meminfo");
- }
- }
-
- void getrunners(unsigned int *running, unsigned int *blocked,
- unsigned int *swapped) {
- static struct direct *ent;
- static char filename[80];
- static int fd;
- static unsigned size;
- static char c;
- DIR *proc;
-
- *running=0;
- *blocked=0;
- *swapped=0;
-
- if ((proc=opendir("/proc"))==NULL) crash("/proc");
-
- while((ent=readdir(proc))) {
- if (isdigit(ent->d_name[0])) { /*just to weed out the obvious junk*/
- sprintf(filename, "/proc/%s/stat", ent->d_name);
- if ((fd = open(filename, O_RDONLY, 0)) != -1) { /*this weeds the rest*/
- 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') {
- if (size>0) (*running)++;
- else (*swapped)++;
- }
- else if (c=='D') {
- if (size>0) (*blocked)++;
- else (*swapped)++;
- }
- }
- }
- }
- closedir(proc);
-
- #if 1
- /* is this next line a good idea? It removes this thing which
- uses (hopefully) little time, from the count of running processes */
- (*running)--;
- #endif
- }
-