1: /* 2: * vmstat-- report system statistics 3: * 4: * This version for use with the 2.9 BSD (Berkeley PDP11) system. 5: */ 6: #include <stdio.h> 7: #include <sys/param.h> 8: #include <sys/vm.h> 9: #include <a.out.h> 10: #include <sys/file.h> 11: 12: #define TIME 5 /* number of seconds for vmrate */ 13: #define MAXDISK 6 /* max disks that can be monitored */ 14: 15: struct nlist nl[] = { 16: #define X_DKBUSY 0 17: "_dk_busy", 0, 0, 18: #define X_RATE 1 19: "_rate", 0, 0, 20: #define X_TOTAL 2 21: "_total", 0, 0, 22: #define X_SUM 3 23: "_sum", 0, 0, 24: #define X_BOOTIME 4 25: "_bootime", 0, 0, 26: #define X_SYTIME 5 27: "_sy_time", 0, 0, 28: #define X_DKTIME 6 29: "_dk_time", 0, 0, 30: #define X_DKNUMB 7 31: "_dk_numb", 0, 0, 32: #define X_NDISK 8 33: "_ndisk", 0, 0, 34: "\0\0\0\0\0\0\0\0", 0, 0 35: }; 36: 37: double stat1(); 38: struct 39: { 40: int busy; 41: long sy_time[8]; 42: long dk_time[1<<MAXDISK]; 43: long numb[MAXDISK]; 44: } s, s1; 45: struct vmrate rate; 46: struct vmtotal total; 47: struct vmsum sum; 48: int ndisk; 49: 50: double etime; 51: int mf; 52: int showmem, showsum; 53: 54: main(argc, argv) 55: char **argv; 56: { 57: time_t now; 58: int lines; 59: extern char *ctime(); 60: register i,j; 61: int iter; 62: long nintv; 63: time_t bootime; 64: double f1, f2; 65: long t; 66: extern char _sobuf[]; 67: 68: setbuf(stdout, _sobuf); 69: if (nlist("/unix", nl) == -1 || (nl[0].n_type == 0)) { 70: fprintf(stderr,"No /unix namelist\n"); 71: exit(1); 72: } 73: if (nl[X_SYTIME].n_type == 0) { 74: fprintf(stderr, 75: "sy_time not in /unix-- wrong version of vmstat\n"); 76: exit(1); 77: } 78: if (nl[X_RATE].n_type == 0) { 79: fprintf(stderr, 80: "Vmstat statistics not maintained in the system\n"); 81: exit(1); 82: } 83: mf = open("/dev/kmem", FATT_RDONLY); 84: if(mf < 0) { 85: perror("/dev/kmem"); 86: exit(1); 87: } 88: lseek(mf, (long)nl[X_BOOTIME].n_value, FSEEK_ABSOLUTE); 89: read(mf, &bootime, sizeof bootime); 90: time(&now); 91: nintv = now - bootime; 92: if (nintv <= 0 || nintv > 60L*60L*24L*365L*10L) { 93: fprintf(stderr, 94: "Time makes no sense... namelist must be wrong.\n"); 95: exit(1); 96: } 97: lseek(mf, (long)nl[X_NDISK].n_value, FSEEK_ABSOLUTE); 98: read(mf, (char *)&ndisk, sizeof ndisk); 99: if (ndisk <= 0 || ndisk > MAXDISK) { 100: fprintf(stderr, "Too many disks monitored (or system mismatch)\n"); 101: exit(1); 102: } 103: iter = 0; 104: argc--, argv++; 105: while (argc>0 && argv[0][0]=='-') { 106: char *cp = *argv++; 107: argc--; 108: while (*++cp) switch (*cp) { 109: 110: case 'z': 111: close(mf); 112: if (access("/dev/kmem", FACCESS_WRITE) != -1) { 113: if ((mf = open("/dev/kmem", FATT_RDWR)) < 0) { 114: perror("/dev/kmem"); 115: exit(1); 116: } 117: lseek(mf, (long)nl[X_SUM].n_value, FSEEK_ABSOLUTE); 118: write(mf, &sum, sizeof sum); 119: exit(0); 120: } 121: else { 122: perror("/dev/kmem"); 123: exit(1); 124: } 125: 126: case 's': 127: dosum(); 128: showsum++; 129: /* exit(0);*/ 130: break; 131: 132: case 'm': 133: showmem++; 134: break; 135: 136: default: 137: fprintf(stderr, 138: "usage: vmstat [ -sm ] [ interval ] [ count]\n"); 139: exit(1); 140: } 141: } 142: if(argc > 1) 143: iter = atoi(argv[1]); 144: reprint: 145: lines = 20; 146: 147: if (!showmem) 148: if (!showsum) { 149: printf( 150: " Procs Virtual Real Swap Disk, tps Faults/sec Cpu, %%\n"); 151: printf( 152: "RQ DW SW AVM TX FRE I O D0 D1 D2 D3 PD IN SY TR OV CS US NI SY ID\n"); 153: } else 154: exit(0); 155: else { 156: printf( 157: " ----- VIRTUAL ------- ------- REAL --------- FREE\n"); 158: printf( 159: " VM VMTXT AVM AVMTXT RM RMT ARM ARMTXT MEM\n"); 160: } 161: 162: loop: 163: if (showmem) { 164: domem(); 165: goto contin; 166: } 167: lseek(mf, (long)nl[X_DKBUSY].n_value, FSEEK_ABSOLUTE); 168: read(mf, (char *)&(s.busy), sizeof (s.busy)); 169: lseek(mf, (long)nl[X_SYTIME].n_value, FSEEK_ABSOLUTE); 170: read(mf, (char *)&(s.sy_time), sizeof (s.sy_time)); 171: lseek(mf, (long)nl[X_DKTIME].n_value, FSEEK_ABSOLUTE); 172: read(mf, (char *)&(s.dk_time), (1 << ndisk) * sizeof (s.dk_time[0])); 173: lseek(mf, (long)nl[X_DKNUMB].n_value, FSEEK_ABSOLUTE); 174: read(mf, (char *)&(s.numb), ndisk * sizeof (s.numb[0])); 175: etime = 0; 176: for(i=0; i < 8; i++) { 177: t = s.sy_time[i]; 178: s.sy_time[i] -= s1.sy_time[i]; 179: s1.sy_time[i] = t; 180: etime += s.sy_time[i]; 181: } 182: if(etime == 0.) 183: etime = 1.; 184: for(i=0; i < (1 << ndisk); i++) { 185: t = s.dk_time[i]; 186: s.dk_time[i] -= s1.dk_time[i]; 187: s1.dk_time[i] = t; 188: } 189: for(i=0; i < ndisk; i++) { 190: t = s.numb[i]; 191: s.numb[i] -= s1.numb[i]; 192: s1.numb[i] = t; 193: } 194: if (nintv != 1) { 195: lseek(mf, (long)nl[X_SUM].n_value, FSEEK_ABSOLUTE); 196: read(mf, &sum, sizeof sum); 197: rate.v_swpin = sum.vs_swpin/(nintv/5); 198: rate.v_swpout = sum.vs_swpout/(nintv/5); 199: rate.v_intr = sum.vs_intr/nintv; 200: rate.v_pdma = sum.vs_pdma/nintv; 201: rate.v_trap = sum.vs_trap/nintv; 202: rate.v_syscall = sum.vs_syscall/nintv; 203: rate.v_ovly = sum.vs_ovly/nintv; 204: rate.v_swtch = sum.vs_swtch/nintv; 205: } else { 206: lseek(mf, (long)nl[X_RATE].n_value, FSEEK_ABSOLUTE); 207: read(mf, &rate, sizeof rate); 208: } 209: lseek(mf, (long)nl[X_TOTAL].n_value, FSEEK_ABSOLUTE); 210: read(mf, &total, sizeof total); 211: 212: /* Procs RQ DW SW */ 213: printf("%2d%3d%3d", total.t_rq, total.t_dw, 214: total.t_sw); 215: 216: /* Memory AVM TX FRE */ 217: printf("%6ld%3d%5d", total.t_avm/16, 218: pct(total.t_avmtxt, total.t_avm), total.t_free); 219: 220: /* Swap I O */ 221: printf("%3d%3d", rate.v_swpin, rate.v_swpout); 222: 223: /* Disk D0 D1 D2 D3 */ 224: etime /= 60.; 225: printf(" "); 226: /* formatted for D0-D3 only; could change header above */ 227: for(i=0; i<4; i++) 228: stats(i); 229: 230: /* Faults PD IN SY TR OV */ 231: printf("%4d%4d%4d%4d %4d", 232: rate.v_pdma/TIME, 233: (rate.v_intr-rate.v_trap)/TIME, 234: rate.v_syscall/TIME, 235: rate.v_trap/TIME, 236: rate.v_ovly/TIME); 237: 238: /* context switches CS */ 239: printf("%4d ", rate.v_swtch/TIME); 240: 241: /* Cpu US NI SY ID */ 242: for(i=0; i < 8; i += 2) 243: printf("%3.0f", stat1(i)); 244: printf("\n"); 245: contin: 246: fflush(stdout); 247: nintv = 1; 248: --iter; 249: if(iter) 250: if(argc > 0) { 251: sleep(atoi(argv[0])); 252: if (--lines <= 0) 253: goto reprint; 254: goto loop; 255: } 256: } 257: 258: dosum() 259: { 260: 261: lseek(mf, (long)nl[X_SUM].n_value, FSEEK_ABSOLUTE); 262: read(mf, &sum, sizeof sum); 263: printf("%9ld swap ins\n", sum.vs_swpin); 264: printf("%9ld swap outs\n", sum.vs_swpout); 265: printf("%9ld pages swapped in\n", sum.vs_pswpin / CLSIZE); 266: printf("%9ld pages swapped out\n", sum.vs_pswpout / CLSIZE); 267: printf("%9ld cpu context switches\n", sum.vs_swtch); 268: printf("%9ld device interrupts\n", sum.vs_intr); 269: printf("%9ld pseudo-DMA interrupts\n", sum.vs_pdma); 270: printf("%9ld traps\n", sum.vs_trap); 271: printf("%9ld system calls\n", sum.vs_syscall); 272: printf("%9ld overlay traps\n", sum.vs_ovly); 273: } 274: 275: domem() { 276: lseek(mf, (long)nl[X_TOTAL].n_value, FSEEK_ABSOLUTE); 277: read(mf, &total, sizeof total); 278: 279: printf("%6ld%6ld%6ld%6ld ", 280: total.t_vm/16, total.t_vmtxt/16, 281: total.t_avm/16, total.t_avmtxt/16); 282: printf("%6d%6d%6d%6d ", 283: total.t_rm/16, total.t_rmtxt/16, 284: total.t_arm/16, total.t_armtxt/16); 285: printf("%6d\n",total.t_free); 286: } 287: 288: stats(dn) 289: { 290: 291: if (dn >= ndisk) { 292: printf(" 0"); 293: return; 294: } 295: printf("%3.0f", s.numb[dn]/etime); 296: } 297: 298: double 299: stat1(row) 300: { 301: double f; 302: 303: f = s.sy_time[row] + s.sy_time[row+1]; 304: return(f*100./(etime*60.)); 305: } 306: 307: pct(top, bot) 308: long top, bot; 309: { 310: int ret; 311: 312: if (bot == 0) 313: return (0); 314: ret = (top * 100) / bot; 315: return ret; 316: }