📄 m_ftx.c
字号:
hp->remaining--; /* get the cpu usage and calculate the cpu percentages */ cputime = pp->pr_time.tv_sec; get_cpu(pp, &pctcpu, &pctwcpu); /* format this entry */ (void) sprintf (fmt, Proc_format, pp->pr_pid, (*get_userid) (pp->pr_uid), pp->pr_pri - PZERO, pp->pr_nice - NZERO, pagetok (pp->pr_size), pagetok (pp->pr_rssize), state_abbrev[pp->pr_state], cputime / 60l, cputime % 60l, pctwcpu, pctcpu, pp->pr_fname); /* return the result */ return (fmt);}/* * check_nlist(nlst) - checks the nlist to see if any symbols were not * found. For every symbol that was not found, a one-line * message is printed to stderr. The routine returns the * number of symbols NOT found. */intcheck_nlist (register struct nlist *nlst){ register int i; /* check to see if we got ALL the symbols we requested */ /* this will write one line to stderr for every symbol not found */ i = 0; while (nlst->n_name != NULL) { if (nlst->n_type == 0) { /* this one wasn't found */ (void) fprintf (stderr, "kernel: no symbol named `%s'\n", nlst->n_name); i = 1; } nlst++; } return (i);}/* * getkval(offset, ptr, size, refstr) - get a value out of the kernel. * "offset" is the byte offset into the kernel for the desired value, * "ptr" points to a buffer into which the value is retrieved, * "size" is the size of the buffer (and the object to retrieve), * "refstr" is a reference string used when printing error meessages, * if "refstr" starts with a '!', then a failure on read will not * be fatal (this may seem like a silly way to do things, but I * really didn't want the overhead of another argument). * */intgetkval ( unsigned long offset, int *ptr, int size, char *refstr){ if (lseek (kmem, (long) offset, 0) == -1) { if (*refstr == '!') refstr++; (void) fprintf (stderr, "%s: lseek to %s: %s\n", myname, refstr, sys_errlist[errno]); quit (22); } if (read (kmem, (char *) ptr, size) == -1) if (*refstr == '!') /* we lost the race with the kernel, process isn't in memory */ return (0); else { (void) fprintf (stderr, "%s: reading %s: %s\n", myname, refstr, sys_errlist[errno]); quit (23); } return (1);}/* comparison routine for qsort *//* * proc_compare - comparison function for "qsort" * Compares the resource consumption of two processes using five * distinct keys. The keys (in descending order of importance) are: * percent cpu, cpu ticks, state, resident set size, total virtual * memory usage. The process states are ordered as follows (from least * to most important): WAIT, zombie, sleep, stop, start, run. The * array declaration below maps a process state index into a number * that reflects this ordering. */unsigned char sorted_state[] ={ 0, /* not used */ 3, /* sleep */ 6, /* run */ 2, /* zombie */ 4, /* stop */ 5, /* start */ 7, /* run on a processor */ 1 /* being swapped (WAIT) */};intproc_compare ( struct prpsinfo **pp1, struct prpsinfo **pp2) { register struct prpsinfo *p1; register struct prpsinfo *p2; register long result; register long d1; register long d2; register timedata_t *td; /* remove one level of indirection */ p1 = *pp1; p2 = *pp2; td = get_timedata(p1); if (td->ltime == -1) d1 = 0; else d1 = td->time - td->ltime; td = get_timedata(p2); if (td->ltime == -1) d2 = 0; else d2 = td->time - td->ltime; /* compare cpu usage */ if ((result = d2 - d1) == 0) { /* use cpticks to break the tie */ if ((result = (PRTOMS(p2) - PRTOMS(p1))) == 0) { /* use process state to break the tie */ if ((result = (long) (sorted_state[p2->pr_state] - sorted_state[p1->pr_state])) == 0) { /* use priority to break the tie */ if ((result = p2->pr_oldpri - p1->pr_oldpri) == 0) { /* use resident set size (rssize) to break the tie */ if ((result = p2->pr_rssize - p1->pr_rssize) == 0) { /* use total memory to break the tie */ result = (p2->pr_size - p1->pr_size); } } } } } return (result); }/*get process table*/voidgetptable (struct prpsinfo *baseptr){ struct prpsinfo *currproc; /* pointer to current proc structure */ int numprocs = 0; struct dirent *direntp; for (rewinddir (procdir); direntp = readdir (procdir);) { int fd; if ((fd = open (direntp->d_name, O_RDONLY)) < 0) continue; currproc = &baseptr[numprocs]; if (ioctl (fd, PIOCPSINFO, currproc) < 0) { (void) close (fd); continue; } numprocs++; (void) close (fd); } if (nproc != numprocs) nproc = numprocs;}/* return the owner of the specified process, for use in commands.c as we're running setuid root */uid_tproc_owner (pid_t pid){ register struct prpsinfo *p; int i; for (i = 0, p = pbase; i < nproc; i++, p++) if (p->pr_pid == pid) return (p->pr_uid); return (-1);}intsetpriority (int dummy, int who, int niceval){ int scale; int prio; pcinfo_t pcinfo; pcparms_t pcparms; tsparms_t *tsparms; strcpy (pcinfo.pc_clname, "TS"); if (priocntl (0, 0, PC_GETCID, (caddr_t) & pcinfo) == -1) return (-1); prio = niceval; if (prio > PRIO_MAX) prio = PRIO_MAX; else if (prio < PRIO_MIN) prio = PRIO_MIN; tsparms = (tsparms_t *) pcparms.pc_clparms; scale = ((tsinfo_t *) pcinfo.pc_clinfo)->ts_maxupri; tsparms->ts_uprilim = tsparms->ts_upri = -(scale * prio) / 20; pcparms.pc_cid = pcinfo.pc_cid; if (priocntl (P_PID, who, PC_SETPARMS, (caddr_t) & pcparms) == -1) return (-1); return (0);}/* * Per-process CPU calculation: * * We emulate actual % CPU usage calculation, since the statistics * kept by FTX are not valid for this purpose. We fake this calculation * by totalling the amount of CPU time used by all processes since the * last update, and dividing this into the CPU time used by the process * in question. For the WCPU value, we average the CPU calculations for the * process over the last td->cnt updates. This means that the first update * when starting top will always be 0% CPU (no big deal), and that WCPU will * be averaged over a varying amount of time (also no big deal). This is * probably the best we can do, since the kernel doesn't keep any of these * statistics itself. * * This method seems to yield good results. The only problems seem to be the * fact that the first update always shows 0%, and that the * sysinfo CPU data isn't always in sync with the per-process CPU usage * when a CPU-intensive process quits. This latter problem causes funny * results, because the remaining processes get credited with the residual * CPU time. * * This algorithm may seem CPU intensive, but it's actually very * inexpensive. The expensive part is the ioctl call to the sar driver. * No amount of optimization in this program will reduce the sar overhead. */voidgetsysinfo (struct sysinfo *sysinfo){ register int i; register int j; register int cpus; /* Get the per-CPU sysinfo data from sar. */ if(ioctl(sar, SAR_SYSINFO, &spa)) { perror("ioctl(sar, SAR_SYSINFO)"); quit(24); } (void)memset((char *)sysinfo, 0, sizeof(struct sysinfo)); /* Average the state times to get systemwide values. */ for(i = 0, cpus = 0; i < MAX_LOG_CPU; i++) { if(cpu_state[i] != SAR_CPU_RUNNING) continue; cpus++; for(j = 0; j < 5; j++) sysinfo->cpu[j] += cpu_sysinfo[i].cpu[j]; } for(i = 0; i < 5; i++) sysinfo->cpu[i] /= cpus;}voidadd_time (struct prpsinfo *pp){ register timedata_t *td; td = get_timedata(pp); td->flags |= TF_USED; if(td->time == -1) { td->time = PRTOMS(pp); if(!(td->flags & TF_NEWPROC)) return; td->flags &= ~TF_NEWPROC; td->ltime = 0; } else { td->ltime = td->time; td->time = PRTOMS(pp); } /* Keep track of the time spent by all processes. */ total_time += td->time - td->ltime;}voidget_cpu(struct prpsinfo *pp, double *cpu, double *wcpu){ register int i; register int j; register long t; register timedata_t *td; td = get_timedata(pp); /* No history, so return 0%. */ if(td->ltime == -1) { *cpu = 0; *wcpu = 0; return; } i = td->index; td->index = (i + 1) % MAXTIMEHIST; td->cnt = MIN((td->cnt + 1), MAXTIMEHIST); /* Compute CPU usage (time diff from last update / total cpu time). */ /* We don't want to div by 0. */ if(total_time == 0) { td->hist[i] = 0; *cpu = 0.0; } else { t = (td->time - td->ltime) * 10000 / total_time * total_cpu; td->hist[i] = t; *cpu = t / 100.0; } /* Compute WCPU usage (average CPU % since oldest update). */ for(j = 0, t = 0; j < td->cnt; j++) { t += td->hist[i]; i--; if(i < 0) i = MAXTIMEHIST - 1; } *wcpu = t / j / 100.0;}timedata_t *get_timedata(struct prpsinfo *pp){ register timedata_t *t; register timedata_t *l; l = TD_HASH(pp->pr_pid); for(t = l->hnext; t != l; t = t->hnext) if(t->pid == pp->pr_pid) return t; t = (timedata_t *)malloc(sizeof(timedata_t)); if(t == 0) { perror("malloc"); quit(25); } t->pid = pp->pr_pid; t->index = 0; t->cnt = 0; t->time = -1; t->ltime = -1; if(initted) t->flags = TF_USED | TF_NEWPROC; else t->flags = TF_USED; /* Put struct on hash list. */ t->hnext = l->hnext; t->hlast = l; l->hnext->hlast = t; l->hnext = t; /* Put struct on timedata list. */ t->lnext = timedata.lnext; t->llast = &timedata; timedata.lnext->llast = t; timedata.lnext = t; return t;}voidclean_timedata(void){ register timedata_t *t; for(t = timedata.lnext; t != &timedata; t = t->lnext) { if(!(t->flags & TF_USED)) { t->hnext->hlast = t->hlast; t->hlast->hnext = t->hnext; t->lnext->llast = t->llast; t->llast->lnext = t->lnext; free(t); } else { t->flags &= ~TF_USED; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -