/* * iostat - bsd like iostat for Linux * * Copyright (c) 1995-1997, Matthew Jacob * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; version 2. * * This software 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. * * You should have received a copy of the GNU Library General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * The author may be reached via electronic communications at * * mjacob@feral.com * * or, via United States Postal Address * * Matthew Jacob * 2343 3rd Street * Suite 30 * San Francisco, CA, 94107 */ /* * $Id: iostat.c,v 1.4 1995/07/13 22:11:01 mjacob Exp mjacob $ * * $Log: iostat.c,v $ * Revision 1.4 1995/07/13 22:11:01 mjacob * Matt, I tried your iostat program under Linux 1.2.8, and I found that * it got divide-by-0 errs when run with a sleep time. Apparently * this Linux version always produces the same results when reading * /proc/stat, despite the rewind. I changed it to open the file each * time get_stats() is called, and now it works. Maybe there's a * cleverer way than this ... but now it works better! * * Regards, * -- James Dugal, jpd@usl.edu * * Revision 1.3 1995/07/10 01:53:26 mjacob * make totcpu an inline * * Revision 1.2 1995/07/10 01:49:11 mjacob * first version- kinda sloppy, but mostly does the trick. * */ #include #include #include #include #include #ifndef STATFILE #define STATFILE "/proc/stat" #endif #define DK_NDRIVE 4 #define CPU_USER 0 #define CPU_NICE 1 #define CPU_SYSTEM 2 #define CPU_IDLE 3 static int get_stats(unsigned int cpu[4], unsigned int dk[4]); static void print_hdr(void); static inline double totcpu(unsigned int c[4]) { double rv; rv = (double) c[0] + (double) c[1] + (double) c[2] + (double) c[3]; return (rv); } int main(int a, char **v) { int i, nprint; unsigned int cpu_times[4], ocpu_times[4]; unsigned int dk_drive[DK_NDRIVE], odk_drive[DK_NDRIVE]; register double ctime, lctime; long sleepincr; sleepincr = 0; if (a > 1) { sleepincr = strtol(v[1], (char **) NULL, 10); if (sleepincr <= 0) { fprintf(stderr, "usage: %s [ repeat-interval ]\n", *v); return (1); } } if (get_stats(ocpu_times, odk_drive)) { return (1); } print_hdr(); for (i = 0; i < DK_NDRIVE; i++) fprintf(stdout, "% 8d", odk_drive[i]); lctime = ctime = totcpu(ocpu_times); fprintf(stdout, " %2.0f %2.0f %2.0f %2.0f\n", (((double) ocpu_times[0]) / ctime) * (double) 100.0, (((double) ocpu_times[1]) / ctime) * (double) 100.0, (((double) ocpu_times[2]) / ctime) * (double) 100.0, (((double) ocpu_times[3]) / ctime) * (double) 100.0); nprint = 0; while (sleepincr > 0) { sleep(sleepincr); if (get_stats(cpu_times, dk_drive)) break; for (i = 0; i < DK_NDRIVE; i++) odk_drive[i] = dk_drive[i] - odk_drive[i]; for (i = 0; i < DK_NDRIVE; i++) { fprintf(stdout, "%8.0f", (double) odk_drive[i] / (double) sleepincr); odk_drive[i] = dk_drive[i]; } ctime = totcpu(cpu_times); for (i = 0; i < 4; i++) { ocpu_times[i] = cpu_times[i] - ocpu_times[i]; } putchar(' '); for (i = 0; i < 4; i++) { fprintf(stdout, " %2.0f", (((double) ocpu_times[i]) / (ctime - lctime)) * 100.0); ocpu_times[i] = cpu_times[i]; } putchar('\n'); lctime = ctime; if (nprint++ >= 16) { print_hdr(); nprint = 0; } } return (0); } static int get_stats(unsigned int cpu[4], unsigned int dk[4]) { int gotcpu, gotdk; char lbuf[132]; FILE *statfp; statfp = fopen(STATFILE, "r"); if (statfp == NULL) { perror(STATFILE); return (-1); } gotcpu = gotdk = 0; while (gotcpu == 0 || gotdk == 0) { if (fgets(lbuf, 132, statfp) == (char *) NULL) { break; } if (strncmp(lbuf, "cpu", 3) == 0) { if (sscanf(lbuf+4, "%u %u %u %u\n", &cpu[0], &cpu[1], &cpu[2], &cpu[3]) != 4) { fprintf(stderr, "bad cpu line in %s\n", STATFILE); } gotcpu++; continue; } if (strncmp(lbuf, "disk", 4) == 0) { if (sscanf(lbuf+5, "%u %u %u %u\n", &dk[0], &dk[1], &dk[2], &dk[3]) != 4) { fprintf(stderr, "bad disk line in %s\n", STATFILE); } gotdk++; continue; } } (void) fclose(statfp); return ((gotcpu && gotdk)? 0 : -1); } static void print_hdr(void) { int i; for (i = 0; i < DK_NDRIVE; i++) { (void) fprintf(stdout, " dk%d", i); } fprintf(stdout, " us ni sy id\n"); } /* * Overrides for Emacs so that we almost follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only. This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-indent-level: 4 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -4 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * indent-tabs-mode: nil * tab-width: 8 * End: */