1// old: "Copyright 1994 by Henry Ware <al172@yfn.ysu.edu>. Copyleft same year." 2// most code copyright 2002 Albert Cahalan 3// 4// 27/05/2003 (Fabian Frederick) : Add unit conversion + interface 5// Export proc/stat access to libproc 6// Adapt vmstat helpfile 7// 31/05/2003 (Fabian) : Add diskstat support (/libproc) 8// June 2003 (Fabian) : -S <x> -s & -s -S <x> patch 9// June 2003 (Fabian) : -Adding diskstat against 3.1.9, slabinfo 10// -patching 'header' in disk & slab 11// July 2003 (Fabian) : -Adding disk partition output 12// -Adding disk table 13// -Syncing help / usage 14 15#include <stdio.h> 16#include <stdlib.h> 17#include <ctype.h> 18#include <string.h> 19#include <assert.h> 20#include <fcntl.h> 21#include <limits.h> 22#include <termios.h> 23#include <unistd.h> 24#include <sys/types.h> 25#include <sys/ioctl.h> 26#include <sys/dir.h> 27#include <dirent.h> 28 29#include "proc/sysinfo.h" 30#include "proc/version.h" 31 32static unsigned long dataUnit=1024; 33static char szDataUnit [16]; 34#define UNIT_B 1 35#define UNIT_k 1000 36#define UNIT_K 1024 37#define UNIT_m 1000000 38#define UNIT_M 1048576 39 40#define VMSTAT 0 41#define DISKSTAT 0x00000001 42#define VMSUMSTAT 0x00000002 43#define SLABSTAT 0x00000004 44#define PARTITIONSTAT 0x00000008 45#define DISKSUMSTAT 0x00000010 46#define ITLBSTAT 0x00000020 47#define DTLBSTAT 0x00000040 48#define CPUCACHESTAT 0x00000080 49 50static int statMode=VMSTAT; 51 52#define FALSE 0 53#define TRUE 1 54 55static int a_option; /* "-a" means "show active/inactive" */ 56 57static unsigned sleep_time = 1; 58static unsigned long num_updates; 59 60static unsigned int height; // window height 61static unsigned int moreheaders=TRUE; 62 63 64///////////////////////////////////////////////////////////////////////// 65 66static void usage(void) NORETURN; 67static void usage(void) { 68 fprintf(stderr,"usage: vmstat [-V] [-n] [delay [count]]\n"); 69 fprintf(stderr," -V prints version.\n"); 70 fprintf(stderr," -n causes the headers not to be reprinted regularly.\n"); 71 fprintf(stderr," -a print inactive/active page stats.\n"); 72 fprintf(stderr," -d prints disk statistics\n"); 73 fprintf(stderr," -D prints disk table\n"); 74 fprintf(stderr," -p prints disk partition statistics\n"); 75 fprintf(stderr," -s prints vm table\n"); 76 fprintf(stderr," -m prints slabinfo\n"); 77 fprintf(stderr," -S unit size\n"); 78 fprintf(stderr," -I ITLB stats\n"); 79 fprintf(stderr," -P DTLB stats\n"); 80 fprintf(stderr," -C I/D cache stats\n"); 81 fprintf(stderr," delay is the delay between updates in seconds. \n"); 82 fprintf(stderr," unit size k:1000 K:1024 m:1000000 M:1048576 (default is K)\n"); 83 fprintf(stderr," count is the number of updates.\n"); 84 exit(EXIT_FAILURE); 85} 86 87///////////////////////////////////////////////////////////////////////////// 88 89 90//////////////////////////////////////////////////////////////////////////// 91 92static void new_header(void){ 93 printf("procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----"); 94 if (statMode & ITLBSTAT) { 95 printf(" -----------itlb------------"); 96 } else if(statMode & DTLBSTAT) { 97 printf(" -------dtlb--------"); 98 } else if (statMode & CPUCACHESTAT) { 99 printf(" ------------i/d cache-------------"); 100 } 101 printf("\n"); 102 103 printf( 104 "%2s %2s %6s %6s %6s %6s %4s %4s %5s %5s %4s %4s %2s %2s %2s %2s", 105 "r","b", 106 "swpd", "free", a_option?"inact":"buff", a_option?"active":"cache", 107 "si","so", 108 "bi","bo", 109 "in","cs", 110 "us","sy","id","wa" 111 ); 112 113 if (statMode & ITLBSTAT) { 114 printf(" %6s %6s %6s", "ia", "im", "jm"); 115 } else if(statMode & DTLBSTAT) { 116 printf(" %6s %6s", "ja", "jm"); 117 } else if (statMode & CPUCACHESTAT) { 118 printf(" %6s %6s %6s %6s", "ia", "im", "dw", "dm"); 119 } 120 121 printf("\n"); 122} 123 124//////////////////////////////////////////////////////////////////////////// 125 126static unsigned long unitConvert(unsigned int size){ 127 float cvSize; 128 cvSize=(float)size/dataUnit*((statMode==SLABSTAT)?1:1024); 129 return ((unsigned long) cvSize); 130} 131 132//////////////////////////////////////////////////////////////////////////// 133 134static void new_format(int mode) { 135 const char format[]="%2u %2u %6lu %6lu %6lu %6lu %4u %4u %5u %5u %4u %4u %2u %2u %2u %2u"; 136 unsigned int tog=0; /* toggle switch for cleaner code */ 137 unsigned int i; 138 unsigned int hz = Hertz; 139 unsigned int running,blocked,dummy_1,dummy_2; 140 jiff cpu_use[2], cpu_nic[2], cpu_sys[2], cpu_idl[2], cpu_iow[2], cpu_xxx[2], cpu_yyy[2], cpu_zzz[2]; 141 jiff duse, dsys, didl, diow, dstl, Div, divo2; 142 unsigned long itlb_access[2], itlb_miss[2], ijtlb_miss[2]; 143 unsigned long itlba, itlbm, ijtlbm; 144 unsigned long djtlb_access[2], djtlb_miss[2]; 145 unsigned long djtlba, djtlbm; 146 unsigned long icache_access[2], icache_miss[2], dcache_wb[2], dcache_miss[2]; 147 unsigned long icachea, icachem, dcachewb, dcachem; 148 unsigned long pgpgin[2], pgpgout[2], pswpin[2], pswpout[2]; 149 unsigned int intr[2], ctxt[2]; 150 unsigned int sleep_half; 151 unsigned long kb_per_page = sysconf(_SC_PAGESIZE) / 1024ul; 152 int debt = 0; // handle idle ticks running backwards 153 154 sleep_half=(sleep_time/2); 155 new_header(); 156 meminfo(); 157 158 getstat(cpu_use,cpu_nic,cpu_sys,cpu_idl,cpu_iow,cpu_xxx,cpu_yyy,cpu_zzz, 159 pgpgin,pgpgout,pswpin,pswpout, 160 intr,ctxt, 161 &running,&blocked, 162 &dummy_1, &dummy_2); 163 164 duse= *cpu_use + *cpu_nic; 165 dsys= *cpu_sys + *cpu_xxx + *cpu_yyy; 166 didl= *cpu_idl; 167 diow= *cpu_iow; 168 dstl= *cpu_zzz; 169 Div= duse+dsys+didl+diow+dstl; 170 divo2= Div/2UL; 171 printf(format, 172 running, blocked, 173 unitConvert(kb_swap_used), unitConvert(kb_main_free), 174 unitConvert(a_option?kb_inactive:kb_main_buffers), 175 unitConvert(a_option?kb_active:kb_main_cached), 176 (unsigned)( (*pswpin * unitConvert(kb_per_page) * hz + divo2) / Div ), 177 (unsigned)( (*pswpout * unitConvert(kb_per_page) * hz + divo2) / Div ), 178 (unsigned)( (*pgpgin * hz + divo2) / Div ), 179 (unsigned)( (*pgpgout * hz + divo2) / Div ), 180 (unsigned)( (*intr * hz + divo2) / Div ), 181 (unsigned)( (*ctxt * hz + divo2) / Div ), 182 (unsigned)( (100*duse + divo2) / Div ), 183 (unsigned)( (100*dsys + divo2) / Div ), 184 (unsigned)( (100*didl + divo2) / Div ), 185 (unsigned)( (100*diow + divo2) / Div ) /* , 186 (unsigned)( (100*dstl + divo2) / Div ) */ 187 ); 188 189 if (mode & ITLBSTAT) { 190 const char format[] = " %6lu %6lu %6lu"; 191 192 getitlbstat(itlb_access, itlb_miss, ijtlb_miss); 193 194 printf(format, *itlb_access, *itlb_miss, *ijtlb_miss); 195 } else if (mode & DTLBSTAT) { 196 const char format[] = " %6lu %6lu"; 197 198 getdjtlbstat(djtlb_access, djtlb_miss); 199 200 printf(format, *djtlb_access, *djtlb_miss); 201 } else if (mode & CPUCACHESTAT) { 202 const char format[] = " %6lu %6lu %6lu %6lu"; 203 204 getcpucachestat(icache_access, icache_miss, dcache_wb, dcache_miss); 205 206 printf(format, *icache_access, *icache_miss, *dcache_wb, *dcache_miss); 207 } 208 209 printf("\n"); 210 211 for(i=1;i<num_updates;i++) { /* \\\\\\\\\\\\\\\\\\\\ main loop ////////////////// */ 212 sleep(sleep_time); 213 if (moreheaders && ((i%height)==0)) new_header(); 214 tog= !tog; 215 216 meminfo(); 217 218 getstat(cpu_use+tog,cpu_nic+tog,cpu_sys+tog,cpu_idl+tog,cpu_iow+tog,cpu_xxx+tog,cpu_yyy+tog,cpu_zzz+tog, 219 pgpgin+tog,pgpgout+tog,pswpin+tog,pswpout+tog, 220 intr+tog,ctxt+tog, 221 &running,&blocked, 222 &dummy_1,&dummy_2); 223 224 duse= cpu_use[tog]-cpu_use[!tog] + cpu_nic[tog]-cpu_nic[!tog]; 225 dsys= cpu_sys[tog]-cpu_sys[!tog] + cpu_xxx[tog]-cpu_xxx[!tog] + cpu_yyy[tog]-cpu_yyy[!tog]; 226 didl= cpu_idl[tog]-cpu_idl[!tog]; 227 diow= cpu_iow[tog]-cpu_iow[!tog]; 228 dstl= cpu_zzz[tog]-cpu_zzz[!tog]; 229 230 /* idle can run backwards for a moment -- kernel "feature" */ 231 if(debt){ 232 didl = (int)didl + debt; 233 debt = 0; 234 } 235 if( (int)didl < 0 ){ 236 debt = (int)didl; 237 didl = 0; 238 } 239 240 Div= duse+dsys+didl+diow+dstl; 241 divo2= Div/2UL; 242 printf(format, 243 running, blocked, 244 unitConvert(kb_swap_used),unitConvert(kb_main_free), 245 unitConvert(a_option?kb_inactive:kb_main_buffers), 246 unitConvert(a_option?kb_active:kb_main_cached), 247 (unsigned)( ( (pswpin [tog] - pswpin [!tog])*unitConvert(kb_per_page)+sleep_half )/sleep_time ), /*si*/ 248 (unsigned)( ( (pswpout[tog] - pswpout[!tog])*unitConvert(kb_per_page)+sleep_half )/sleep_time ), /*so*/ 249 (unsigned)( ( pgpgin [tog] - pgpgin [!tog] +sleep_half )/sleep_time ), /*bi*/ 250 (unsigned)( ( pgpgout[tog] - pgpgout[!tog] +sleep_half )/sleep_time ), /*bo*/ 251 (unsigned)( ( intr [tog] - intr [!tog] +sleep_half )/sleep_time ), /*in*/ 252 (unsigned)( ( ctxt [tog] - ctxt [!tog] +sleep_half )/sleep_time ), /*cs*/ 253 (unsigned)( (100*duse+divo2)/Div ), /*us*/ 254 (unsigned)( (100*dsys+divo2)/Div ), /*sy*/ 255 (unsigned)( (100*didl+divo2)/Div ), /*id*/ 256 (unsigned)( (100*diow+divo2)/Div )/*, //wa 257 (unsigned)( (100*dstl+divo2)/Div ) //st */ 258 ); 259 260 if (mode & ITLBSTAT) { 261 const char format[] = " %6lu %6lu %6lu"; 262 263 getitlbstat(itlb_access+tog, itlb_miss+tog, ijtlb_miss+tog); 264 265 itlba = itlb_access[tog]-itlb_access[!tog]; 266 itlbm = itlb_miss[tog]-itlb_miss[!tog]; 267 ijtlbm = ijtlb_miss[tog]-ijtlb_miss[!tog]; 268 printf(format, itlba, itlbm, ijtlbm); 269 270 } else if (mode & DTLBSTAT) { 271 const char format[] = " %6lu %6lu"; 272 273 getdjtlbstat(djtlb_access+tog, djtlb_miss+tog); 274 275 djtlba = djtlb_access[tog]-djtlb_access[!tog]; 276 djtlbm = djtlb_miss[tog]-djtlb_miss[!tog]; 277 printf(format, djtlba, djtlbm); 278 279 } else if (mode & CPUCACHESTAT) { 280 const char format[] = " %6lu %6lu %6lu %6lu"; 281 282 getcpucachestat(icache_access+tog, icache_miss+tog, dcache_wb+tog, dcache_miss+tog); 283 284 icachea = icache_access[tog]-icache_access[!tog]; 285 icachem = icache_miss[tog]-icache_miss[!tog]; 286 dcachewb = dcache_wb[tog]-dcache_wb[!tog]; 287 dcachem = dcache_miss[tog]-dcache_miss[!tog]; 288 printf(format, icachea, icachem, dcachewb, dcachem); 289 } 290 printf("\n"); 291 } 292} 293 294//////////////////////////////////////////////////////////////////////////// 295 296static void diskpartition_header(const char *partition_name){ 297 printf("%-10s %10s %10s %10s %10s\n",partition_name, "reads ", "read sectors", "writes ", "requested writes"); 298} 299 300//////////////////////////////////////////////////////////////////////////// 301 302static int diskpartition_format(const char* partition_name){ 303 FILE *fDiskstat; 304 struct disk_stat *disks; 305 struct partition_stat *partitions, *current_partition=NULL; 306 unsigned long ndisks, j, k, npartitions; 307 const char format[] = "%20u %10llu %10u %10u\n"; 308 309 fDiskstat=fopen("/proc/diskstats","rb"); 310 if(!fDiskstat){ 311 fprintf(stderr, "Your kernel doesn't support diskstat. (2.5.70 or above required)\n"); 312 exit(0); 313 } 314 315 fclose(fDiskstat); 316 ndisks=getdiskstat(&disks,&partitions); 317 npartitions=getpartitions_num(disks, ndisks); 318 for(k=0; k<npartitions; k++){ 319 if(!strcmp(partition_name, partitions[k].partition_name)){ 320 current_partition=&(partitions[k]); 321 } 322 } 323 if(!current_partition){ 324 return -1; 325 } 326 diskpartition_header(partition_name); 327 printf (format, 328 current_partition->reads,current_partition->reads_sectors,current_partition->writes,current_partition->requested_writes); 329 fflush(stdout); 330 free(disks); 331 free(partitions); 332 for(j=1; j<num_updates; j++){ 333 if (moreheaders && ((j%height)==0)) diskpartition_header(partition_name); 334 sleep(sleep_time); 335 ndisks=getdiskstat(&disks,&partitions); 336 npartitions=getpartitions_num(disks, ndisks); 337 current_partition=NULL; 338 for(k=0; k<npartitions; k++){ 339 if(!strcmp(partition_name, partitions[k].partition_name)){ 340 current_partition=&(partitions[k]); 341 } 342 } 343 if(!current_partition){ 344 return -1; 345 } 346 printf (format, 347 current_partition->reads,current_partition->reads_sectors,current_partition->writes,current_partition->requested_writes); 348 fflush(stdout); 349 free(disks); 350 free(partitions); 351 } 352 return 0; 353} 354 355//////////////////////////////////////////////////////////////////////////// 356 357static void diskheader(void){ 358 printf("disk- ------------reads------------ ------------writes----------- -----IO------\n"); 359 360 printf("%5s %6s %6s %7s %7s %6s %6s %7s %7s %6s %6s\n", 361 " ", "total", "merged","sectors","ms","total","merged","sectors","ms","cur","sec"); 362 363} 364 365//////////////////////////////////////////////////////////////////////////// 366 367static void diskformat(void){ 368 FILE *fDiskstat; 369 struct disk_stat *disks; 370 struct partition_stat *partitions; 371 unsigned long ndisks,i,j,k; 372 const char format[]="%-5s %6u %6u %7llu %7u %6u %6u %7llu %7u %6u %6u\n"; 373 if ((fDiskstat=fopen("/proc/diskstats", "rb"))){ 374 fclose(fDiskstat); 375 ndisks=getdiskstat(&disks,&partitions); 376 for(k=0; k<ndisks; k++){ 377 if (moreheaders && ((k%height)==0)) diskheader(); 378 printf(format, 379 disks[k].disk_name, 380 disks[k].reads, 381 disks[k].merged_reads, 382 disks[k].reads_sectors, 383 disks[k].milli_reading, 384 disks[k].writes, 385 disks[k].merged_writes, 386 disks[k].written_sectors, 387 disks[k].milli_writing, 388 disks[k].inprogress_IO?disks[k].inprogress_IO/1000:0, 389 disks[k].milli_spent_IO?disks[k].milli_spent_IO/1000:0/*, 390 disks[i].weighted_milli_spent_IO/1000*/ 391 ); 392 fflush(stdout); 393 } 394 free(disks); 395 free(partitions); 396 for(j=1; j<num_updates; j++){ 397 sleep(sleep_time); 398 ndisks=getdiskstat(&disks,&partitions); 399 for(i=0; i<ndisks; i++,k++){ 400 if (moreheaders && ((k%height)==0)) diskheader(); 401 printf(format, 402 disks[i].disk_name, 403 disks[i].reads, 404 disks[i].merged_reads, 405 disks[i].reads_sectors, 406 disks[i].milli_reading, 407 disks[i].writes, 408 disks[i].merged_writes, 409 disks[i].written_sectors, 410 disks[i].milli_writing, 411 disks[i].inprogress_IO?disks[i].inprogress_IO/1000:0, 412 disks[i].milli_spent_IO?disks[i].milli_spent_IO/1000:0/*, 413 disks[i].weighted_milli_spent_IO/1000*/ 414 ); 415 fflush(stdout); 416 } 417 free(disks); 418 free(partitions); 419 } 420 }else{ 421 fprintf(stderr, "Your kernel doesn't support diskstat (2.5.70 or above required)\n"); 422 exit(0); 423 } 424} 425 426//////////////////////////////////////////////////////////////////////////// 427 428static void slabheader(void){ 429 printf("%-24s %6s %6s %6s %6s\n","Cache","Num", "Total", "Size", "Pages"); 430} 431 432//////////////////////////////////////////////////////////////////////////// 433 434static void slabformat (void){ 435 FILE *fSlab; 436 struct slab_cache *slabs; 437 unsigned long nSlab,i,j,k; 438 const char format[]="%-24s %6u %6u %6u %6u\n"; 439 440 fSlab=fopen("/proc/slabinfo", "rb"); 441 if(!fSlab){ 442 fprintf(stderr, "Your kernel doesn't support slabinfo.\n"); 443 return; 444 } 445 446 nSlab = getslabinfo(&slabs); 447 for(k=0; k<nSlab; k++){ 448 if (moreheaders && ((k%height)==0)) slabheader(); 449 printf(format, 450 slabs[k].name, 451 slabs[k].active_objs, 452 slabs[k].num_objs, 453 slabs[k].objsize, 454 slabs[k].objperslab 455 ); 456 } 457 free(slabs); 458 for(j=1,k=1; j<num_updates; j++) { 459 sleep(sleep_time); 460 nSlab = getslabinfo(&slabs); 461 for(i=0; i<nSlab; i++,k++){ 462 if (moreheaders && ((k%height)==0)) slabheader(); 463 printf(format, 464 slabs[i].name, 465 slabs[i].active_objs, 466 slabs[i].num_objs, 467 slabs[i].objsize, 468 slabs[i].objperslab 469 ); 470 } 471 free(slabs); 472 } 473} 474 475//////////////////////////////////////////////////////////////////////////// 476 477static void disksum_format(void) { 478 479 FILE *fDiskstat; 480 struct disk_stat *disks; 481 struct partition_stat *partitions; 482 int ndisks, i; 483 unsigned long reads, merged_reads, read_sectors, milli_reading, writes, 484 merged_writes, written_sectors, milli_writing, inprogress_IO, 485 milli_spent_IO, weighted_milli_spent_IO; 486 487 reads=merged_reads=read_sectors=milli_reading=writes=merged_writes= \ 488 written_sectors=milli_writing=inprogress_IO=milli_spent_IO= \ 489 weighted_milli_spent_IO=0; 490 491 if ((fDiskstat=fopen("/proc/diskstats", "rb"))){ 492 fclose(fDiskstat); 493 ndisks=getdiskstat(&disks, &partitions); 494 printf("%13d disks \n", ndisks); 495 printf("%13d partitions \n", getpartitions_num(disks, ndisks)); 496 497 for(i=0; i<ndisks; i++){ 498 reads+=disks[i].reads; 499 merged_reads+=disks[i].merged_reads; 500 read_sectors+=disks[i].reads_sectors; 501 milli_reading+=disks[i].milli_reading; 502 writes+=disks[i].writes; 503 merged_writes+=disks[i].merged_writes; 504 written_sectors+=disks[i].written_sectors; 505 milli_writing+=disks[i].milli_writing; 506 inprogress_IO+=disks[i].inprogress_IO?disks[i].inprogress_IO/1000:0; 507 milli_spent_IO+=disks[i].milli_spent_IO?disks[i].milli_spent_IO/1000:0; 508 } 509 510 printf("%13lu total reads\n",reads); 511 printf("%13lu merged reads\n",merged_reads); 512 printf("%13lu read sectors\n",read_sectors); 513 printf("%13lu milli reading\n",milli_reading); 514 printf("%13lu writes\n",writes); 515 printf("%13lu merged writes\n",merged_writes); 516 printf("%13lu written sectors\n",written_sectors); 517 printf("%13lu milli writing\n",milli_writing); 518 printf("%13lu inprogress IO\n",inprogress_IO); 519 printf("%13lu milli spent IO\n",milli_spent_IO); 520 521 free(disks); 522 free(partitions); 523 } 524} 525 526//////////////////////////////////////////////////////////////////////////// 527 528static void sum_format(void) { 529 unsigned int running, blocked, btime, processes; 530 jiff cpu_use, cpu_nic, cpu_sys, cpu_idl, cpu_iow, cpu_xxx, cpu_yyy, cpu_zzz; 531 unsigned long pgpgin, pgpgout, pswpin, pswpout; 532 unsigned int intr, ctxt; 533 534 meminfo(); 535 536 getstat(&cpu_use, &cpu_nic, &cpu_sys, &cpu_idl, 537 &cpu_iow, &cpu_xxx, &cpu_yyy, &cpu_zzz, 538 &pgpgin, &pgpgout, &pswpin, &pswpout, 539 &intr, &ctxt, 540 &running, &blocked, 541 &btime, &processes); 542 543 printf("%13lu %s total memory\n", unitConvert(kb_main_total),szDataUnit); 544 printf("%13lu %s used memory\n", unitConvert(kb_main_used),szDataUnit); 545 printf("%13lu %s active memory\n", unitConvert(kb_active),szDataUnit); 546 printf("%13lu %s inactive memory\n", unitConvert(kb_inactive),szDataUnit); 547 printf("%13lu %s free memory\n", unitConvert(kb_main_free),szDataUnit); 548 printf("%13lu %s buffer memory\n", unitConvert(kb_main_buffers),szDataUnit); 549 printf("%13lu %s swap cache\n", unitConvert(kb_main_cached),szDataUnit); 550 printf("%13lu %s total swap\n", unitConvert(kb_swap_total),szDataUnit); 551 printf("%13lu %s used swap\n", unitConvert(kb_swap_used),szDataUnit); 552 printf("%13lu %s free swap\n", unitConvert(kb_swap_free),szDataUnit); 553 printf("%13Lu non-nice user cpu ticks\n", cpu_use); 554 printf("%13Lu nice user cpu ticks\n", cpu_nic); 555 printf("%13Lu system cpu ticks\n", cpu_sys); 556 printf("%13Lu idle cpu ticks\n", cpu_idl); 557 printf("%13Lu IO-wait cpu ticks\n", cpu_iow); 558 printf("%13Lu IRQ cpu ticks\n", cpu_xxx); 559 printf("%13Lu softirq cpu ticks\n", cpu_yyy); 560 printf("%13Lu stolen cpu ticks\n", cpu_zzz); 561 printf("%13lu pages paged in\n", pgpgin); 562 printf("%13lu pages paged out\n", pgpgout); 563 printf("%13lu pages swapped in\n", pswpin); 564 printf("%13lu pages swapped out\n", pswpout); 565 printf("%13u interrupts\n", intr); 566 printf("%13u CPU context switches\n", ctxt); 567 printf("%13u boot time\n", btime); 568 printf("%13u forks\n", processes); 569} 570 571//////////////////////////////////////////////////////////////////////////// 572 573static void fork_format(void) { 574 unsigned int running, blocked, btime, processes; 575 jiff cpu_use, cpu_nic, cpu_sys, cpu_idl, cpu_iow, cpu_xxx, cpu_yyy, cpu_zzz; 576 unsigned long pgpgin, pgpgout, pswpin, pswpout; 577 unsigned int intr, ctxt; 578 579 getstat(&cpu_use, &cpu_nic, &cpu_sys, &cpu_idl, 580 &cpu_iow, &cpu_xxx, &cpu_yyy, &cpu_zzz, 581 &pgpgin, &pgpgout, &pswpin, &pswpout, 582 &intr, &ctxt, 583 &running, &blocked, 584 &btime, &processes); 585 586 printf("%13u forks\n", processes); 587} 588 589//////////////////////////////////////////////////////////////////////////// 590 591static int winhi(void) { 592 struct winsize win; 593 int rows = 24; 594 595 if (ioctl(1, TIOCGWINSZ, &win) != -1 && win.ws_row > 0) 596 rows = win.ws_row; 597 598 return rows; 599} 600 601//////////////////////////////////////////////////////////////////////////// 602 603int main(int argc, char *argv[]) { 604 char partition[16]; 605 unsigned long perfopt; 606 607 argc=0; /* redefined as number of integer arguments */ 608 for (argv++;*argv;argv++) { 609 if ('-' ==(**argv)) { 610 switch (*(++(*argv))) { 611 612 case 'V': 613 //display_version(); 614 exit(0); 615 case 'd': 616 statMode |= DISKSTAT; 617 break; 618 case 'a': 619 /* active/inactive mode */ 620 a_option=1; 621 break; 622 case 'f': 623 fork_format(); 624 exit(0); 625 case 'm': 626 statMode |= SLABSTAT; 627 break; 628 case 'D': 629 statMode |= DISKSUMSTAT; 630 break; 631 case 'I': 632 statMode |= ITLBSTAT; 633 break; 634 case 'P': 635 statMode |= DTLBSTAT; 636 break; 637 case 'C': 638 statMode |= CPUCACHESTAT; 639 break; 640 case 'n': 641 /* print only one header */ 642 moreheaders=FALSE; 643 break; 644 case 'p': 645 statMode |= PARTITIONSTAT; 646 if (argv[1]){ 647 char *cp = *++argv; 648 if(!memcmp(cp,"/dev/",5)) cp += 5; 649 snprintf(partition, sizeof partition, "%s", cp); 650 }else{ 651 fprintf(stderr, "-p requires an argument\n"); 652 exit(EXIT_FAILURE); 653 } 654 break; 655 case 'S': 656 if (argv[1]){ 657 ++argv; 658 if (!strcmp(*argv, "k")) dataUnit=UNIT_k; 659 else if (!strcmp(*argv, "K")) dataUnit=UNIT_K; 660 else if (!strcmp(*argv, "m")) dataUnit=UNIT_m; 661 else if (!strcmp(*argv, "M")) dataUnit=UNIT_M; 662 else {fprintf(stderr, "-S requires k, K, m or M (default is kb)\n"); 663 exit(EXIT_FAILURE); 664 } 665 strcpy(szDataUnit, *argv); 666 }else {fprintf(stderr, "-S requires an argument\n"); 667 exit(EXIT_FAILURE); 668 } 669 break; 670 case 's': 671 statMode |= VMSUMSTAT; 672 break; 673 default: 674 /* no other aguments defined yet. */ 675 usage(); 676 } 677 }else{ 678 argc++; 679 switch (argc) { 680 case 1: 681 if ((sleep_time = atoi(*argv)) == 0) 682 usage(); 683 num_updates = ULONG_MAX; 684 break; 685 case 2: 686 num_updates = atol(*argv); 687 break; 688 default: 689 usage(); 690 } /* switch */ 691 } 692} 693 perfopt = (statMode & (ITLBSTAT | DTLBSTAT | CPUCACHESTAT)); 694 if (perfopt & (perfopt - 1)) { 695 printf("May use only one among I/P/C options\n"); 696 exit(0); 697 } 698 699 if (moreheaders) { 700 int tmp=winhi()-3; 701 height=((tmp>0)?tmp:22); 702 } 703 setlinebuf(stdout); 704 switch(statMode){ 705 case(VMSTAT): 706 case(ITLBSTAT): 707 case(DTLBSTAT): 708 case(CPUCACHESTAT): new_format(statMode); 709 break; 710 case(VMSUMSTAT): sum_format(); 711 break; 712 case(DISKSTAT): diskformat(); 713 break; 714 case(PARTITIONSTAT): if(diskpartition_format(partition)==-1) 715 printf("Partition was not found\n"); 716 break; 717 case(SLABSTAT): slabformat(); 718 break; 719 case(DISKSUMSTAT): disksum_format(); 720 break; 721 default: usage(); 722 break; 723 } 724 return 0; 725} 726