?? top.c
字號:
#ifdef CASEUP_SCALE static char nextup[] = { 'K', 'M', 'G', 'T', 0 };#else static char nextup[] = { 'k', 'm', 'g', 't', 0 };#endif static char buf[TNYBUFSIZ]; double *dp; char *up; /* try an unscaled version first... */ if (width >= snprintf(buf, sizeof(buf), "%lu", num)) return buf; /* now try successively higher types until it fits */ for (up = nextup + type, dp = scale; *dp; ++dp, ++up) { /* the most accurate version */ if (width >= snprintf(buf, sizeof(buf), "%.1f%c", num / *dp, *up)) return buf; /* the integer version */ if (width >= snprintf(buf, sizeof(buf), "%ld%c", (unsigned long)(num / *dp), *up)) return buf; } /* well shoot, this outta' fit... */ return "?";} /* * Do some scaling stuff. * format 'tics' to fit 'width'. */static const char *scale_tics (TIC_t tics, const int width){#ifdef CASEUP_SCALE#define HH "%uH"#define DD "%uD"#define WW "%uW"#else#define HH "%uh"#define DD "%ud"#define WW "%uw"#endif static char buf[TNYBUFSIZ]; unsigned long nt; // narrow time, for speed on 32-bit unsigned cc; // centiseconds unsigned nn; // multi-purpose whatever nt = (tics * 100ull) / Hertz; cc = nt % 100; // centiseconds past second nt /= 100; // total seconds nn = nt % 60; // seconds past the minute nt /= 60; // total minutes if (width >= snprintf(buf, sizeof(buf), "%lu:%02u.%02u", nt, nn, cc)) return buf; if (width >= snprintf(buf, sizeof buf, "%lu:%02u", nt, nn)) return buf; nn = nt % 60; // minutes past the hour nt /= 60; // total hours if (width >= snprintf(buf, sizeof buf, "%lu,%02u", nt, nn)) return buf; nn = nt; // now also hours if (width >= snprintf(buf, sizeof buf, HH, nn)) return buf; nn /= 24; // now days if (width >= snprintf(buf, sizeof buf, DD, nn)) return buf; nn /= 7; // now weeks if (width >= snprintf(buf, sizeof buf, WW, nn)) return buf; // well shoot, this outta' fit... return "?";#undef HH#undef DD#undef WW}#include <pwd.h>static int selection_type;static uid_t selection_uid;// FIXME: this is "temporary" code we hopestatic int good_uid(const proc_t *restrict const pp){ switch(selection_type){ case 'p': return 1; case 0: return 1; case 'U': if (pp->ruid == selection_uid) return 1; if (pp->suid == selection_uid) return 1; if (pp->fuid == selection_uid) return 1; // FALLTHROUGH case 'u': if (pp->euid == selection_uid) return 1; // FALLTHROUGH default: ; // don't know what it is; find bugs fast } return 0;}// swiped from ps, and ought to be in libprocstatic const char *parse_uid(const char *restrict const str, uid_t *restrict const ret){ struct passwd *passwd_data; char *endp; unsigned long num; static const char uidrange[] = "User ID out of range."; static const char uidexist[] = "User name does not exist."; num = strtoul(str, &endp, 0); if(*endp != '\0'){ /* hmmm, try as login name */ passwd_data = getpwnam(str); if(!passwd_data) return uidexist; num = passwd_data->pw_uid; } if(num > 0xfffffffeUL) return uidrange; *ret = num; return 0;}/*###### Library Alternatives ##########################################*/ /* * Handle our own memory stuff without the risk of leaving the * user's terminal in an ugly state should things go sour. */static void *alloc_c (unsigned numb) MALLOC;static void *alloc_c (unsigned numb){ void * p; if (!numb) ++numb; if (!(p = calloc(1, numb))) std_err("failed memory allocate"); return p;}static void *alloc_r (void *q, unsigned numb) MALLOC;static void *alloc_r (void *q, unsigned numb){ void *p; if (!numb) ++numb; if (!(p = realloc(q, numb))) std_err("failed memory allocate"); return p;} /* * This guy's modeled on libproc's 'five_cpu_numbers' function except * we preserve all cpu data in our CPU_t array which is organized * as follows: * cpus[0] thru cpus[n] == tics for each separate cpu * cpus[Cpu_tot] == tics from the 1st /proc/stat line */static CPU_t *cpus_refresh (CPU_t *cpus){ static FILE *fp = NULL; int i; int num; // enough for a /proc/stat CPU line (not the intr line) char buf[SMLBUFSIZ]; /* by opening this file once, we'll avoid the hit on minor page faults (sorry Linux, but you'll have to close it for us) */ if (!fp) { if (!(fp = fopen("/proc/stat", "r"))) std_err(fmtmk("Failed /proc/stat open: %s", strerror(errno))); /* note: we allocate one more CPU_t than Cpu_tot so that the last slot can hold tics representing the /proc/stat cpu summary (the first line read) -- that slot supports our View_CPUSUM toggle */ cpus = alloc_c((1 + Cpu_tot) * sizeof(CPU_t)); } rewind(fp); fflush(fp); // first value the last slot with the cpu summary line if (!fgets(buf, sizeof(buf), fp)) std_err("failed /proc/stat read"); cpus[Cpu_tot].x = 0; // FIXME: can't tell by kernel version number cpus[Cpu_tot].y = 0; // FIXME: can't tell by kernel version number cpus[Cpu_tot].z = 0; // FIXME: can't tell by kernel version number num = sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu", &cpus[Cpu_tot].u, &cpus[Cpu_tot].n, &cpus[Cpu_tot].s, &cpus[Cpu_tot].i, &cpus[Cpu_tot].w, &cpus[Cpu_tot].x, &cpus[Cpu_tot].y, &cpus[Cpu_tot].z ); if (num < 4) std_err("failed /proc/stat read"); // and just in case we're 2.2.xx compiled without SMP support... if (Cpu_tot == 1) { cpus[1].id = 0; memcpy(cpus, &cpus[1], sizeof(CPU_t)); } // now value each separate cpu's tics for (i = 0; 1 < Cpu_tot && i < Cpu_tot; i++) { if (!fgets(buf, sizeof(buf), fp)) std_err("failed /proc/stat read"); cpus[i].x = 0; // FIXME: can't tell by kernel version number cpus[i].y = 0; // FIXME: can't tell by kernel version number cpus[i].z = 0; // FIXME: can't tell by kernel version number num = sscanf(buf, "cpu%u %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu", &cpus[i].id, &cpus[i].u, &cpus[i].n, &cpus[i].s, &cpus[i].i, &cpus[i].w, &cpus[i].x, &cpus[i].y, &cpus[i].z ); if (num < 4) std_err("failed /proc/stat read"); } return cpus;} /* * Refresh procs *Helper* function to eliminate yet one more need * to loop through our darn proc_t table. He's responsible for: * 1) calculating the elapsed time since the previous frame * 2) counting the number of tasks in each state (run, sleep, etc) * 3) maintaining the HST_t's and priming the proc_t pcpu field * 4) establishing the total number tasks for this frame */static void prochlp (proc_t *this){ static HST_t *hist_sav = NULL; static HST_t *hist_new = NULL; static unsigned hist_siz = 0; // number of structs static unsigned maxt_sav; // prior frame's max tasks TIC_t tics; if (unlikely(!this)) { static struct timeval oldtimev; struct timeval timev; struct timezone timez; HST_t *hist_tmp; float et; gettimeofday(&timev, &timez); et = (timev.tv_sec - oldtimev.tv_sec) + (float)(timev.tv_usec - oldtimev.tv_usec) / 1000000.0; oldtimev.tv_sec = timev.tv_sec; oldtimev.tv_usec = timev.tv_usec; // if in Solaris mode, adjust our scaling for all cpus Frame_tscale = 100.0f / ((float)Hertz * (float)et * (Rc.mode_irixps ? 1 : Cpu_tot)); maxt_sav = Frame_maxtask; Frame_maxtask = Frame_running = Frame_sleepin = Frame_stopped = Frame_zombied = 0; // reuse memory each time around hist_tmp = hist_sav; hist_sav = hist_new; hist_new = hist_tmp; // prep for our binary search by sorting the last frame's HST_t's qsort(hist_sav, maxt_sav, sizeof(HST_t), (QFP_t)sort_HST_t); return; } switch (this->state) { case 'R': Frame_running++; break; case 'S': case 'D': Frame_sleepin++; break; case 'T': Frame_stopped++; break; case 'Z': Frame_zombied++; break; } if (unlikely(Frame_maxtask+1 >= hist_siz)) { hist_siz = hist_siz * 5 / 4 + 100; // grow by at least 25% hist_sav = alloc_r(hist_sav, sizeof(HST_t) * hist_siz); hist_new = alloc_r(hist_new, sizeof(HST_t) * hist_siz); } /* calculate time in this process; the sum of user time (utime) and system time (stime) -- but PLEASE dont waste time and effort on calcs and saves that go unused, like the old top! */ hist_new[Frame_maxtask].pid = this->tid; hist_new[Frame_maxtask].tics = tics = (this->utime + this->stime);#if 0{ int i; int lo = 0; int hi = maxt_sav - 1; // find matching entry from previous frame and make ticks elapsed while (lo <= hi) { i = (lo + hi) / 2; if (this->tid < hist_sav[i].pid) hi = i - 1; else if (likely(this->tid > hist_sav[i].pid)) lo = i + 1; else { tics -= hist_sav[i].tics; break; } }}#else{ HST_t tmp; const HST_t *ptr; tmp.pid = this->tid; ptr = bsearch(&tmp, hist_sav, maxt_sav, sizeof tmp, sort_HST_t); if(ptr) tics -= ptr->tics;}#endif // we're just saving elapsed tics, to be converted into %cpu if // this task wins it's displayable screen row lottery... */ this->pcpu = tics;// if (Frames_maxcmdln) { } // shout this to the world with the final call (or us the next time in) Frame_maxtask++;} /* * This guy's modeled on libproc's 'readproctab' function except * we reuse and extend any prior proc_t's. He's been customized * for our specific needs and to avoid the use of <stdarg.h> */static proc_t **procs_refresh (proc_t **table, int flags){#define PTRsz sizeof(proc_t *)#define ENTsz sizeof(proc_t) static unsigned savmax = 0; // first time, Bypass: (i) proc_t *ptsk = (proc_t *)-1; // first time, Force: (ii) unsigned curmax = 0; // every time (jeeze) PROCTAB* PT; static int show_threads_was_enabled = 0; // optimization prochlp(NULL); // prep for a new frame if (Monpidsidx) PT = openproc(flags, Monpids); else PT = openproc(flags); // i) Allocated Chunks: *Existing* table; refresh + reuse if (!(CHKw(Curwin, Show_THREADS))) { while (curmax < savmax) { if (table[curmax]->cmdline) { unsigned idx; // Skip if Show_THREADS was never enabled if (show_threads_was_enabled) { for (idx = curmax + 1; idx < savmax; idx++) { if (table[idx]->cmdline == table[curmax]->cmdline) table[idx]->cmdline = NULL; } } free(*table[curmax]->cmdline); table[curmax]->cmdline = NULL; } if (unlikely(!(ptsk = readproc(PT, table[curmax])))) break; prochlp(ptsk); // tally & complete this proc_t ++curmax; } } else { // show each thread in a process separately while (curmax < savmax) { proc_t *ttsk; if (unlikely(!(ptsk = readproc(PT, NULL)))) break; show_threads_was_enabled = 1; while (curmax < savmax) { unsigned idx; if (table[curmax]->cmdline) { // threads share the same cmdline storage. 'table' is // qsort()ed, so must look through the rest of the table. for (idx = curmax + 1; idx < savmax; idx++) { if (table[idx]->cmdline == table[curmax]->cmdline) table[idx]->cmdline = NULL; } free(*table[curmax]->cmdline); // only free once
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -