1/* 2 * top - a top users display for Unix 3 * 4 * SYNOPSIS: For FreeBSD-2.x and later 5 * 6 * DESCRIPTION: 7 * Originally written for BSD4.4 system by Christos Zoulas. 8 * Ported to FreeBSD 2.x by Steven Wallace && Wolfram Schneider --- 6 unchanged lines hidden (view full) --- 15 * 16 * LIBS: -lkvm 17 * 18 * AUTHOR: Christos Zoulas <christos@ee.cornell.edu> 19 * Steven Wallace <swallace@freebsd.org> 20 * Wolfram Schneider <wosch@FreeBSD.org> 21 * Thomas Moestl <tmoestl@gmx.net> 22 * |
23 * $FreeBSD: head/usr.bin/top/machine.c 131402 2004-07-01 09:12:38Z alfred $ |
24 */ 25 26 27#include <sys/time.h> 28#include <sys/types.h> 29#include <sys/signal.h> 30#include <sys/param.h> 31 --- 26 unchanged lines hidden (view full) --- 58 59static void getsysctl(char *, void *, size_t); 60 61#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) 62 63extern char* printable(char *); 64int swapmode(int *retavail, int *retfree); 65static int smpmode; |
66enum displaymodes displaymode; |
67static int namelength; 68static int cmdlengthdelta; 69 70/* Prototypes for top internals */ 71void quit(int); |
72int compare_pid(const void *a, const void *b); |
73 74/* get_process_info passes back a handle. This is what it looks like: */ 75 76struct handle 77{ 78 struct kinfo_proc **next_proc; /* points to next valid proc pointer */ 79 int remaining; /* number of pointers remaining */ 80}; 81 82/* declarations for load_avg */ 83#include "loadavg.h" 84 85/* define what weighted cpu is. */ 86#define weighted_cpu(pct, pp) ((pp)->ki_swtime == 0 ? 0.0 : \ 87 ((pct) / (1.0 - exp((pp)->ki_swtime * logcpu)))) 88 89/* what we consider to be process size: */ 90#define PROCSIZE(pp) ((pp)->ki_size / 1024) 91 |
92#define RU(pp) (&(pp)->ki_rusage) 93#define RUTOT(pp) \ 94 (RU(pp)->ru_inblock + RU(pp)->ru_oublock + RU(pp)->ru_majflt) 95 96 |
97/* definitions for indices in the nlist array */ 98 99/* 100 * These definitions control the format of the per-process area 101 */ 102 |
103static char io_header[] = 104 " PID %-*.*s READ WRITE FAULT TOTAL COMMAND"; 105 106#define io_Proc_format \ 107 "%5d %-*.*s %6d %6d %6d %6d %.*s" 108 |
109static char smp_header[] = 110 " PID %-*.*s PRI NICE SIZE RES STATE C TIME WCPU CPU COMMAND"; 111 112#define smp_Proc_format \ 113 "%5d %-*.*s %3d %4d%7s %6s %-6.6s %1x%7s %5.2f%% %5.2f%% %.*s" 114 115static char up_header[] = 116 " PID %-*.*s PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND"; --- 67 unchanged lines hidden (view full) --- 184 185/* these are for keeping track of the proc array */ 186 187static int nproc; 188static int onproc = -1; 189static int pref_len; 190static struct kinfo_proc *pbase; 191static struct kinfo_proc **pref; |
192static struct kinfo_proc *previous_procs; 193static struct kinfo_proc **previous_pref; 194static int previous_proc_count = 0; 195static int previous_proc_count_max = 0; |
196 197/* these are for getting the memory statistics */ 198 199static int pageshift; /* log base 2 of the pagesize */ 200 201/* define pagetok in terms of pageshift */ 202 203#define pagetok(size) ((size) << pageshift) --- 71 unchanged lines hidden (view full) --- 275} 276 277char * 278format_header(uname_field) 279 char *uname_field; 280 281{ 282 static char Header[128]; |
283 const char *prehead; |
284 |
285 switch (displaymode) { 286 case DISP_CPU: 287 prehead = smpmode ? smp_header : up_header; 288 break; 289 case DISP_IO: 290 prehead = io_header; 291 break; 292 } 293 294 snprintf(Header, sizeof(Header), prehead, |
295 namelength, namelength, uname_field); 296 297 cmdlengthdelta = strlen(Header) - 7; 298 299 return Header; 300} 301 302static int swappgsin = -1; --- 106 unchanged lines hidden (view full) --- 409 if (sysctl(mib, 2, &boottime, &bt_size, NULL, 0) != -1 && 410 boottime.tv_sec != 0) { 411 si->boottime = boottime; 412 } else { 413 si->boottime.tv_sec = -1; 414 } 415} 416 |
417const struct kinfo_proc * 418get_old_proc(struct kinfo_proc *pp) 419{ 420 struct kinfo_proc **oldpp, *oldp; 421 422 if (previous_proc_count == 0) 423 return (NULL); 424 oldpp = bsearch(&pp, previous_pref, previous_proc_count, 425 sizeof(struct kinfo_proc *), compare_pid); 426 if (oldpp == NULL) 427 return (NULL); 428 oldp = *oldpp; 429 if (bcmp(&oldp->ki_start, &pp->ki_start, sizeof(pp->ki_start)) != 0) 430 return (NULL); 431 return (oldp); 432} 433 434long 435get_io_total(struct kinfo_proc *pp) 436{ 437 const struct kinfo_proc *oldp; 438 static struct kinfo_proc dummy; 439 long ret; 440 441 oldp = get_old_proc(pp); 442 if (oldp == NULL) { 443 bzero(&dummy, sizeof(dummy)); 444 oldp = &dummy; 445 } 446 447 ret = 448 (RU(pp)->ru_inblock - RU(oldp)->ru_inblock) + 449 (RU(pp)->ru_oublock - RU(oldp)->ru_oublock) + 450 (RU(pp)->ru_majflt - RU(oldp)->ru_majflt); 451 return (ret); 452} 453 |
454static struct handle handle; 455 456caddr_t 457get_process_info(si, sel, compare) 458 struct system_info *si; 459 struct process_select *sel; 460 int (*compare)(); 461{ --- 6 unchanged lines hidden (view full) --- 468 469 /* these are copied out of sel for speed */ 470 int show_idle; 471 int show_self; 472 int show_system; 473 int show_uid; 474 int show_command; 475 |
476 /* 477 * Save the previous process info. 478 */ 479 if (previous_proc_count_max < nproc) { 480 free(previous_procs); 481 previous_procs = malloc(nproc * sizeof(struct kinfo_proc)); 482 free(previous_pref); 483 previous_pref = malloc(nproc * sizeof(struct kinfo_proc *)); 484 if (previous_procs == NULL || previous_pref == NULL) { 485 (void) fprintf(stderr, "top: Out of memory.\n"); 486 quit(23); 487 } 488 previous_proc_count_max = nproc; 489 } 490 if (nproc) { 491 for (i = 0; i < nproc; i++) 492 previous_pref[i] = &previous_procs[i]; 493 bcopy(pbase, previous_procs, nproc * sizeof(struct kinfo_proc)); 494 qsort(previous_pref, nproc, 495 sizeof(struct kinfo_proc *), compare_pid); 496 } 497 previous_proc_count = nproc; 498 |
499 pbase = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc); 500 if (nproc > onproc) 501 pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *) 502 * (onproc = nproc)); 503 if (pref == NULL || pbase == NULL) { 504 (void) fprintf(stderr, "top: Out of memory.\n"); 505 quit(23); 506 } --- 22 unchanged lines hidden (view full) --- 529 */ 530 if (pp->ki_stat != 0 && 531 (show_self != pp->ki_pid) && 532 (show_system || ((pp->ki_flag & P_SYSTEM) == 0))) 533 { 534 total_procs++; 535 process_states[(unsigned char) pp->ki_stat]++; 536 if ((pp->ki_stat != SZOMB) && |
537 (displaymode == DISP_CPU && 538 (show_idle || (pp->ki_pctcpu != 0) || pp->ki_stat == SRUN)) || 539 (show_idle || (displaymode == DISP_IO && get_io_total(pp))) && |
540 (!show_uid || pp->ki_ruid == (uid_t)sel->uid)) 541 { 542 /* 543 * When not showing threads, take the first thread 544 * for output and add the fields that we can from 545 * the rest of the process's threads rather than 546 * using the system's mostly-broken KERN_PROC_PROC. 547 */ --- 29 unchanged lines hidden (view full) --- 577char fmt[128]; /* static area where result is built */ 578 579char * 580format_next_process(handle, get_userid) 581 caddr_t handle; 582 char *(*get_userid)(); 583{ 584 struct kinfo_proc *pp; |
585 const struct kinfo_proc *oldp; |
586 long cputime; 587 double pct; 588 struct handle *hp; 589 char status[16]; 590 int state; |
591 struct rusage ru, *rup; |
592 593 /* find and remember the next proc structure */ 594 hp = (struct handle *)handle; 595 pp = *(hp->next_proc++); 596 hp->remaining--; 597 598 /* get the process's command name */ 599 if ((pp->ki_sflag & PS_INMEM) == 0) { --- 46 unchanged lines hidden (view full) --- 646 if (state >= 0 && 647 state < sizeof(state_abbrev) / sizeof(*state_abbrev)) 648 sprintf(status, "%.6s", state_abbrev[(unsigned char) state]); 649 else 650 sprintf(status, "?%5d", state); 651 break; 652 } 653 |
654 if (displaymode == DISP_IO) { 655 oldp = get_old_proc(pp); 656 if (oldp != NULL) { 657 ru.ru_inblock = RU(pp)->ru_inblock - RU(oldp)->ru_inblock; 658 ru.ru_oublock = RU(pp)->ru_oublock - RU(oldp)->ru_oublock; 659 ru.ru_majflt = RU(pp)->ru_majflt - RU(oldp)->ru_majflt; 660 rup = &ru; 661 } else { 662 rup = RU(pp); 663 } 664 665 sprintf(fmt, io_Proc_format, 666 pp->ki_pid, 667 namelength, namelength, 668 (*get_userid)(pp->ki_ruid), 669 (int)rup->ru_inblock, 670 (int)rup->ru_oublock, 671 (int)rup->ru_majflt, 672 (int)(rup->ru_inblock + rup->ru_oublock + rup->ru_majflt), 673 screen_width > cmdlengthdelta ? 674 screen_width - cmdlengthdelta : 0, 675 printable(pp->ki_comm)); 676 return (fmt); 677 } |
678 /* format this entry */ 679 sprintf(fmt, 680 smpmode ? smp_Proc_format : up_Proc_format, 681 pp->ki_pid, 682 namelength, namelength, 683 (*get_userid)(pp->ki_ruid), 684 pp->ki_pri.pri_level - PZERO, 685 --- 40 unchanged lines hidden (view full) --- 726 fprintf(stderr, "top: sysctl(%s...) expected %lu, got %lu\n", name, 727 (unsigned long)len, (unsigned long)nlen); 728 quit(23); 729 } 730} 731 732/* comparison routines for qsort */ 733 |
734int 735compare_pid(p1, p2) 736 const void *p1, *p2; 737{ 738 const struct kinfo_proc * const *pp1 = p1; 739 const struct kinfo_proc * const *pp2 = p2; 740 741 if ((*pp2)->ki_pid < 0 || (*pp1)->ki_pid < 0) 742 abort(); 743 744 return ((*pp1)->ki_pid - (*pp2)->ki_pid); 745} 746 |
747/* 748 * proc_compare - comparison function for "qsort" 749 * Compares the resource consumption of two processes using five 750 * distinct keys. The keys (in descending order of importance) are: 751 * percent cpu, cpu ticks, state, resident set size, total virtual 752 * memory usage. The process states are ordered as follows (from least 753 * to most important): WAIT, zombie, sleep, stop, start, run. The 754 * array declaration below maps a process state index into a number --- 181 unchanged lines hidden (view full) --- 936 ORDERKEY_RSSIZE 937 ORDERKEY_MEM 938 ; 939 940 return(result); 941} 942#endif 943 |
944int 945io_compare(pp1, pp2) 946 struct kinfo_proc **pp1, **pp2; 947{ 948 long t1, t2; 949 950 t1 = get_io_total(*pp1); 951 t2 = get_io_total(*pp2); 952 return (t2 - t1); 953} |
954/* 955 * proc_owner(pid) - returns the uid that owns process "pid", or -1 if 956 * the process does not exist. 957 * It is EXTREMLY IMPORTANT that this function work correctly. 958 * If top runs setuid root (as in SVR4), then this function 959 * is the only thing that stands in the way of a serious 960 * security problem. It validates requests for the "kill" 961 * and "renice" commands. --- 49 unchanged lines hidden --- |