1 /* 2 * Copyright (c) 1980, 1986, 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1980, 1986, 1991 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)vmstat.c 5.26 (Berkeley) 04/24/91"; 16 #endif /* not lint */ 17 18 #include <sys/param.h> 19 #include <sys/vm.h> 20 #include <sys/user.h> 21 #include <sys/dkstat.h> 22 #include <sys/buf.h> 23 #include <sys/namei.h> 24 #include <sys/text.h> 25 #include <sys/malloc.h> 26 #include <signal.h> 27 #include <fcntl.h> 28 #include <time.h> 29 #include <nlist.h> 30 #include <kvm.h> 31 #include <errno.h> 32 #include <unistd.h> 33 #include <stdio.h> 34 #include <ctype.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <paths.h> 38 39 struct nlist nl[] = { 40 #define X_CPTIME 0 41 { "_cp_time" }, 42 #define X_RATE 1 43 { "_rate" }, 44 #define X_TOTAL 2 45 { "_total" }, 46 #define X_DEFICIT 3 47 { "_deficit" }, 48 #define X_FORKSTAT 4 49 { "_forkstat" }, 50 #define X_SUM 5 51 { "_sum" }, 52 #define X_BOOTTIME 6 53 { "_boottime" }, 54 #define X_DKXFER 7 55 { "_dk_xfer" }, 56 #define X_REC 8 57 { "_rectime" }, 58 #define X_PGIN 9 59 { "_pgintime" }, 60 #define X_HZ 10 61 { "_hz" }, 62 #define X_PHZ 11 63 { "_phz" }, 64 #define X_NCHSTATS 12 65 { "_nchstats" }, 66 #define X_INTRNAMES 13 67 { "_intrnames" }, 68 #define X_EINTRNAMES 14 69 { "_eintrnames" }, 70 #define X_INTRCNT 15 71 { "_intrcnt" }, 72 #define X_EINTRCNT 16 73 { "_eintrcnt" }, 74 #define X_DK_NDRIVE 17 75 { "_dk_ndrive" }, 76 #define X_XSTATS 18 77 { "_xstats" }, 78 #define X_KMEMSTAT 19 79 { "_kmemstats" }, 80 #define X_KMEMBUCKETS 20 81 { "_bucket" }, 82 #define X_END 20 83 #ifdef hp300 84 #define X_HPDINIT (X_END+1) 85 { "_hp_dinit" }, 86 #endif 87 #ifdef tahoe 88 #define X_VBDINIT (X_END+1) 89 { "_vbdinit" }, 90 #define X_CKEYSTATS (X_END+2) 91 { "_ckeystats" }, 92 #define X_DKEYSTATS (X_END+3) 93 { "_dkeystats" }, 94 #endif 95 #ifdef vax 96 #define X_MBDINIT (X_END+1) 97 { "_mbdinit" }, 98 #define X_UBDINIT (X_END+2) 99 { "_ubdinit" }, 100 #endif 101 { "" }, 102 }; 103 104 struct _disk { 105 long time[CPUSTATES]; 106 long *xfer; 107 } cur, last; 108 109 struct vmmeter sum; 110 char *vmunix = _PATH_UNIX; 111 char **dr_name; 112 int *dr_select, dk_ndrive, ndrives; 113 114 #define FORKSTAT 0x01 115 #define INTRSTAT 0x02 116 #define MEMSTAT 0x04 117 #define SUMSTAT 0x08 118 #define TIMESTAT 0x10 119 #define VMSTAT 0x20 120 #define ZEROOUT 0x40 121 122 #include "names.c" /* disk names -- machine dependent */ 123 124 void cpustats(), dkstats(), doforkst(), dointr(), domem(), dosum(); 125 void dotimes(), dovmstat(), kread(), usage(), zero(); 126 127 main(argc, argv) 128 register int argc; 129 register char **argv; 130 { 131 extern int optind; 132 extern char *optarg; 133 register int c, todo; 134 u_int interval; 135 int reps; 136 char *kmem; 137 138 kmem = NULL; 139 interval = reps = todo = 0; 140 while ((c = getopt(argc, argv, "c:fiM:mN:stw:z")) != EOF) { 141 switch (c) { 142 case 'c': 143 reps = atoi(optarg); 144 break; 145 case 'f': 146 todo |= FORKSTAT; 147 break; 148 case 'i': 149 todo |= INTRSTAT; 150 break; 151 case 'M': 152 kmem = optarg; 153 break; 154 case 'm': 155 todo |= MEMSTAT; 156 break; 157 case 'N': 158 vmunix = optarg; 159 break; 160 case 's': 161 todo |= SUMSTAT; 162 break; 163 case 't': 164 todo |= TIMESTAT; 165 break; 166 case 'w': 167 interval = atoi(optarg); 168 break; 169 case 'z': 170 todo |= ZEROOUT; 171 break; 172 case '?': 173 default: 174 usage(); 175 } 176 } 177 argc -= optind; 178 argv += optind; 179 180 if (todo & ZEROOUT) { 181 if (todo & ~ZEROOUT || kmem) 182 usage(); 183 zero(); 184 exit(0); 185 } 186 187 if (todo == 0) 188 todo = VMSTAT; 189 190 if (kvm_openfiles(vmunix, kmem, NULL) < 0) { 191 (void)fprintf(stderr, 192 "vmstat: kvm_openfiles: %s\n", kvm_geterr()); 193 exit(1); 194 } 195 196 (void)kvm_nlist(nl); 197 if (nl[0].n_type == 0) { 198 (void)fprintf(stderr, 199 "vmstat: %s: no namelist\n", vmunix); 200 exit(1); 201 } 202 203 if (todo & VMSTAT) { 204 char **getdrivedata(); 205 206 argv = getdrivedata(argv); 207 } 208 209 #define BACKWARD_COMPATIBILITY 210 #ifdef BACKWARD_COMPATIBILITY 211 if (*argv) { 212 interval = atoi(*argv); 213 if (*++argv) 214 reps = atoi(*argv); 215 } 216 #endif 217 218 if (interval) { 219 if (!reps) 220 reps = -1; 221 } else 222 if (reps) 223 interval = 1; 224 225 if (todo & FORKSTAT) 226 doforkst(); 227 if (todo & MEMSTAT) 228 domem(); 229 if (todo & SUMSTAT) 230 dosum(); 231 if (todo & TIMESTAT) 232 dotimes(); 233 if (todo & INTRSTAT) 234 dointr(); 235 if (todo & VMSTAT) 236 dovmstat(interval, reps); 237 exit(0); 238 } 239 240 char ** 241 getdrivedata(argv) 242 char **argv; 243 { 244 register int i; 245 register char **cp; 246 char buf[30]; 247 248 kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive)); 249 if (dk_ndrive <= 0) { 250 (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive); 251 exit(1); 252 } 253 dr_select = calloc((size_t)dk_ndrive, sizeof(int)); 254 dr_name = calloc((size_t)dk_ndrive, sizeof(char *)); 255 for (i = 0; i < dk_ndrive; i++) 256 dr_name[i] = NULL; 257 cur.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 258 last.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 259 read_names(); 260 for (i = 0; i < dk_ndrive; i++) 261 if (dr_name[i] == NULL) { 262 (void)sprintf(buf, "??%d", i); 263 dr_name[i] = strdup(buf); 264 } 265 266 /* 267 * Choose drives to be displayed. Priority goes to (in order) drives 268 * supplied as arguments, default drives. If everything isn't filled 269 * in and there are drives not taken care of, display the first few 270 * that fit. 271 */ 272 #define BACKWARD_COMPATIBILITY 273 for (ndrives = 0; *argv; ++argv) { 274 #ifdef BACKWARD_COMPATIBILITY 275 if (isdigit(**argv)) 276 break; 277 #endif 278 for (i = 0; i < dk_ndrive; i++) { 279 if (strcmp(dr_name[i], *argv)) 280 continue; 281 dr_select[i] = 1; 282 ++ndrives; 283 break; 284 } 285 } 286 for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 287 if (dr_select[i]) 288 continue; 289 for (cp = defdrives; *cp; cp++) 290 if (strcmp(dr_name[i], *cp) == 0) { 291 dr_select[i] = 1; 292 ++ndrives; 293 break; 294 } 295 } 296 for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 297 if (dr_select[i]) 298 continue; 299 dr_select[i] = 1; 300 ++ndrives; 301 } 302 return(argv); 303 } 304 305 long 306 getuptime() 307 { 308 static time_t now, boottime; 309 time_t uptime; 310 311 if (boottime == 0) 312 kread(X_BOOTTIME, &boottime, sizeof(boottime)); 313 (void)time(&now); 314 uptime = now - boottime; 315 if (uptime <= 0 || uptime > 60*60*24*365*10) { 316 (void)fprintf(stderr, 317 "vmstat: time makes no sense; namelist must be wrong.\n"); 318 exit(1); 319 } 320 return(uptime); 321 } 322 323 int hz; 324 325 void 326 dovmstat(interval, reps) 327 u_int interval; 328 int reps; 329 { 330 struct vmmeter rate; 331 struct vmtotal total; 332 time_t uptime; 333 int deficit, hdrcnt; 334 void printhdr(); 335 336 uptime = getuptime(); 337 (void)signal(SIGCONT, printhdr); 338 339 if (nl[X_PHZ].n_type != 0 && nl[X_PHZ].n_value != 0) 340 kread(X_PHZ, &hz, sizeof(hz)); 341 if (!hz) 342 kread(X_HZ, &hz, sizeof(hz)); 343 344 for (hdrcnt = 1;;) { 345 if (!--hdrcnt) { 346 printhdr(); 347 hdrcnt = 20; 348 } 349 kread(X_CPTIME, cur.time, sizeof(cur.time)); 350 kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer * dk_ndrive)); 351 if (uptime != 1) 352 kread(X_SUM, &rate, sizeof(rate)); 353 else 354 kread(X_RATE, &rate, sizeof(rate)); 355 kread(X_TOTAL, &total, sizeof(total)); 356 kread(X_SUM, &sum, sizeof(sum)); 357 kread(X_DEFICIT, &deficit, sizeof(deficit)); 358 (void)printf("%2d%2d%2d", 359 total.t_rq, total.t_dw + total.t_pw, total.t_sw); 360 #define pgtok(a) ((a)*NBPG >> 10) 361 (void)printf("%6ld%6ld", 362 pgtok(total.t_avm), pgtok(total.t_free)); 363 (void)printf("%4lu%3lu", 364 (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec)) / uptime, 365 (rate.v_xsfrec+rate.v_xifrec) / uptime); 366 (void)printf("%4lu", pgtok(rate.v_pgpgin) / uptime); 367 (void)printf("%4lu%4lu%4d%4lu", pgtok(rate.v_pgpgout) / uptime, 368 pgtok(rate.v_dfree) / uptime, 369 pgtok(deficit), rate.v_scan / uptime); 370 dkstats(); 371 (void)printf("%4lu%4lu%4lu", rate.v_intr / uptime, 372 rate.v_syscall / uptime, rate.v_swtch / uptime); 373 cpustats(); 374 (void)printf("\n"); 375 (void)fflush(stdout); 376 uptime = 1; 377 if (reps >= 0 && --reps <= 0) 378 break; 379 (void)sleep(interval); 380 } 381 } 382 383 void 384 printhdr() 385 { 386 register int i; 387 388 (void)printf(" procs memory page%*s", 22, ""); 389 if (ndrives > 1) 390 (void)printf("disks %*s faults cpu\n", 391 ndrives * 3 - 6, ""); 392 else 393 (void)printf("%*s faults cpu\n", ndrives * 3, ""); 394 (void)printf(" r b w avm fre re at pi po fr de sr "); 395 for (i = 0; i < dk_ndrive; i++) 396 if (dr_select[i]) 397 (void)printf("%c%c ", dr_name[i][0], 398 dr_name[i][strlen(dr_name[i]) - 1]); 399 (void)printf(" in sy cs us sy id\n"); 400 } 401 402 void 403 dotimes() 404 { 405 u_int pgintime, rectime; 406 407 kread(X_REC, &rectime, sizeof(rectime)); 408 kread(X_PGIN, &pgintime, sizeof(pgintime)); 409 kread(X_SUM, &sum, sizeof(sum)); 410 (void)printf("%u reclaims, %u total time (usec)\n", 411 sum.v_pgrec, rectime); 412 (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 413 (void)printf("\n"); 414 (void)printf("%u page ins, %u total time (msec)\n", 415 sum.v_pgin, pgintime / 10); 416 (void)printf("average: %8.1f msec / page in\n", 417 pgintime / (sum.v_pgin * 10.0)); 418 } 419 420 pct(top, bot) 421 long top, bot; 422 { 423 if (bot == 0) 424 return(0); 425 return((top * 100) / bot); 426 } 427 428 #define PCT(top, bot) pct((long)(top), (long)(bot)) 429 430 #if defined(tahoe) 431 #include <machine/cpu.h> 432 #endif 433 434 void 435 dosum() 436 { 437 struct nchstats nchstats; 438 struct xstats xstats; 439 long nchtotal; 440 #if defined(tahoe) 441 struct keystats keystats; 442 #endif 443 444 kread(X_SUM, &sum, sizeof(sum)); 445 (void)printf("%9u swap ins\n", sum.v_swpin); 446 (void)printf("%9u swap outs\n", sum.v_swpout); 447 (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); 448 (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); 449 (void)printf("%9u total address trans. faults taken\n", sum.v_faults); 450 (void)printf("%9u page ins\n", sum.v_pgin); 451 (void)printf("%9u page outs\n", sum.v_pgout); 452 (void)printf("%9u pages paged in\n", sum.v_pgpgin); 453 (void)printf("%9u pages paged out\n", sum.v_pgpgout); 454 (void)printf("%9u sequential process pages freed\n", sum.v_seqfree); 455 (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, 456 PCT(sum.v_fastpgrec, sum.v_pgrec)); 457 (void)printf("%9u reclaims from free list\n", sum.v_pgfrec); 458 (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 459 (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); 460 (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); 461 (void)printf("%9u executable fill pages created\n", 462 sum.v_nexfod / CLSIZE); 463 (void)printf("%9u executable fill page faults\n", 464 sum.v_exfod / CLSIZE); 465 (void)printf("%9u swap text pages found in free list\n", 466 sum.v_xsfrec); 467 (void)printf("%9u inode text pages found in free list\n", 468 sum.v_xifrec); 469 (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); 470 (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); 471 (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan); 472 (void)printf("%9u revolutions of the clock hand\n", sum.v_rev); 473 (void)printf("%9u pages freed by the clock daemon\n", 474 sum.v_dfree / CLSIZE); 475 (void)printf("%9u cpu context switches\n", sum.v_swtch); 476 (void)printf("%9u device interrupts\n", sum.v_intr); 477 (void)printf("%9u software interrupts\n", sum.v_soft); 478 #ifdef vax 479 (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); 480 #endif 481 (void)printf("%9u traps\n", sum.v_trap); 482 (void)printf("%9u system calls\n", sum.v_syscall); 483 kread(X_NCHSTATS, &nchstats, sizeof(nchstats)); 484 nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + 485 nchstats.ncs_badhits + nchstats.ncs_falsehits + 486 nchstats.ncs_miss + nchstats.ncs_long; 487 (void)printf("%9ld total name lookups\n", nchtotal); 488 (void)printf( 489 "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", 490 "", PCT(nchstats.ncs_goodhits, nchtotal), 491 PCT(nchstats.ncs_neghits, nchtotal), 492 PCT(nchstats.ncs_pass2, nchtotal)); 493 (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", 494 PCT(nchstats.ncs_badhits, nchtotal), 495 PCT(nchstats.ncs_falsehits, nchtotal), 496 PCT(nchstats.ncs_long, nchtotal)); 497 kread(X_XSTATS, &xstats, sizeof(xstats)); 498 (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n", 499 xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); 500 (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "", 501 xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); 502 (void)printf("%9lu total calls to xfree", xstats.free); 503 (void)printf(" (sticky %lu cached %lu swapped %lu)\n", 504 xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); 505 #if defined(tahoe) 506 kread(X_CKEYSTATS, &keystats, sizeof(keystats)); 507 (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 508 keystats.ks_allocs, "code cache keys allocated", 509 PCT(keystats.ks_allocfree, keystats.ks_allocs), 510 PCT(keystats.ks_norefs, keystats.ks_allocs), 511 PCT(keystats.ks_taken, keystats.ks_allocs), 512 PCT(keystats.ks_shared, keystats.ks_allocs)); 513 kread(X_DKEYSTATS, &keystats, sizeof(keystats)); 514 (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 515 keystats.ks_allocs, "data cache keys allocated", 516 PCT(keystats.ks_allocfree, keystats.ks_allocs), 517 PCT(keystats.ks_norefs, keystats.ks_allocs), 518 PCT(keystats.ks_taken, keystats.ks_allocs), 519 PCT(keystats.ks_shared, keystats.ks_allocs)); 520 #endif 521 } 522 523 void 524 doforkst() 525 { 526 struct forkstat fks; 527 528 kread(X_FORKSTAT, &fks, sizeof(struct forkstat)); 529 (void)printf("%d forks, %d pages, average %.2f\n", 530 fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); 531 (void)printf("%d vforks, %d pages, average %.2f\n", 532 fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork); 533 } 534 535 void 536 dkstats() 537 { 538 register int dn, state; 539 double etime; 540 long tmp; 541 542 for (dn = 0; dn < dk_ndrive; ++dn) { 543 tmp = cur.xfer[dn]; 544 cur.xfer[dn] -= last.xfer[dn]; 545 last.xfer[dn] = tmp; 546 } 547 etime = 0; 548 for (state = 0; state < CPUSTATES; ++state) { 549 tmp = cur.time[state]; 550 cur.time[state] -= last.time[state]; 551 last.time[state] = tmp; 552 etime += cur.time[state]; 553 } 554 if (etime == 0) 555 etime = 1; 556 etime /= hz; 557 for (dn = 0; dn < dk_ndrive; ++dn) { 558 if (!dr_select[dn]) 559 continue; 560 (void)printf("%3.0f", cur.xfer[dn] / etime); 561 } 562 } 563 564 void 565 cpustats() 566 { 567 register int state; 568 double pct, total; 569 570 total = 0; 571 for (state = 0; state < CPUSTATES; ++state) 572 total += cur.time[state]; 573 if (total) 574 pct = 100 / total; 575 else 576 pct = 0; 577 (void)printf("%3.0f", /* user + nice */ 578 (cur.time[0] + cur.time[1]) * pct); 579 (void)printf("%3.0f", cur.time[2] * pct); /* system */ 580 (void)printf("%3.0f", cur.time[3] * pct); /* idle */ 581 } 582 583 void 584 dointr() 585 { 586 register long *intrcnt, inttotal, uptime; 587 register int nintr, inamlen; 588 register char *intrname; 589 590 uptime = getuptime(); 591 nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value; 592 inamlen = nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value; 593 intrcnt = malloc((size_t)nintr); 594 intrname = malloc((size_t)inamlen); 595 if (intrcnt == NULL || intrname == NULL) { 596 (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno)); 597 exit(1); 598 } 599 kread(X_INTRCNT, intrcnt, (size_t)nintr); 600 kread(X_INTRNAMES, intrname, (size_t)inamlen); 601 (void)printf("interrupt total rate\n"); 602 inttotal = 0; 603 nintr /= sizeof(long); 604 while (--nintr >= 0) { 605 if (*intrcnt) 606 (void)printf("%-12s %8ld %8ld\n", intrname, 607 *intrcnt, *intrcnt / uptime); 608 intrname += strlen(intrname) + 1; 609 inttotal += *intrcnt++; 610 } 611 (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); 612 } 613 614 /* 615 * These names are defined in <sys/malloc.h>. 616 */ 617 char *kmemnames[] = INITKMEMNAMES; 618 619 void 620 domem() 621 { 622 register struct kmembuckets *kp; 623 register struct kmemstats *ks; 624 register int i; 625 struct kmemstats kmemstats[M_LAST]; 626 struct kmembuckets buckets[MINBUCKET + 16]; 627 628 kread(X_KMEMBUCKETS, buckets, sizeof(buckets)); 629 (void)printf("Memory statistics by bucket size\n"); 630 (void)printf( 631 " Size In Use Free Requests HighWater Couldfree\n"); 632 for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { 633 if (kp->kb_calls == 0) 634 continue; 635 (void)printf("%8d%9ld%7ld%11ld%8ld%11ld\n", 1 << i, 636 kp->kb_total - kp->kb_totalfree, 637 kp->kb_totalfree, kp->kb_calls, 638 kp->kb_highwat, kp->kb_couldfree); 639 640 } 641 kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats)); 642 (void)printf("\nMemory statistics by type\n"); 643 (void)printf( 644 " Type In Use MemUse HighUse Limit Requests TypeLimit KernLimit\n"); 645 for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 646 if (ks->ks_calls == 0) 647 continue; 648 (void)printf("%10s%7ld%8ldK%9ldK%6ldK%9ld%7u%10u\n", 649 kmemnames[i] ? kmemnames[i] : "undefined", 650 ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 651 (ks->ks_maxused + 1023) / 1024, 652 (ks->ks_limit + 1023) / 1024, ks->ks_calls, 653 ks->ks_limblocks, ks->ks_mapblocks); 654 } 655 } 656 657 void 658 zero() 659 { 660 struct nlist znl[] = { 661 #undef X_SUM 662 #define X_SUM 0 663 { "_sum" }, 664 { "" }, 665 }; 666 int fd; 667 char *kmem; 668 669 if (geteuid()) { 670 (void)fprintf(stderr, "vmstat: %s\n", strerror(EPERM)); 671 exit(1); 672 } 673 /* 674 * Zeroing the statistics is fundamentally different 675 * (and really belongs in a separate program). 676 */ 677 if (nlist(vmunix, znl) || nl[0].n_type == 0) { 678 (void)fprintf(stderr, "vmstat: %s: symbol %s not found\n", 679 vmunix, nl[0].n_name); 680 exit(1); 681 } 682 683 kmem = _PATH_KMEM; 684 if ((fd = open(kmem, O_RDWR)) < 0) { 685 (void)fprintf(stderr, 686 "vmstat: %s: %s\n", kmem, strerror(errno)); 687 exit(1); 688 } 689 if (lseek(fd, (long)nl[0].n_value, L_SET) == -1 || 690 write(fd, &sum, sizeof(sum)) != sizeof(sum)) { 691 (void)fprintf(stderr, 692 "vmstat: %s: %s\n", kmem, strerror(errno)); 693 exit(1); 694 } 695 } 696 697 /* 698 * kread reads something from the kernel, given its nlist index. 699 */ 700 void 701 kread(nlx, addr, size) 702 int nlx; 703 void *addr; 704 size_t size; 705 { 706 char *sym; 707 708 if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) { 709 sym = nl[nlx].n_name; 710 if (*sym == '_') 711 ++sym; 712 (void)fprintf(stderr, 713 "vmstat: %s: symbol %s not defined\n", vmunix, sym); 714 exit(1); 715 } 716 if (kvm_read((void *)nl[nlx].n_value, addr, size) != size) { 717 sym = nl[nlx].n_name; 718 if (*sym == '_') 719 ++sym; 720 (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr()); 721 exit(1); 722 } 723 } 724 725 void 726 usage() 727 { 728 (void)fprintf(stderr, 729 "usage: vmstat [-fimst] [-c count] [-M core] \ 730 [-N system] [-w wait] [disks]\n vmstat -z\n"); 731 exit(1); 732 } 733