📄 top.c
字号:
time/=60; /* minutes */ sprintf(buf,"%dm",time); if (strlen(buf)<=width) return buf; time/=60; /* hours */ sprintf(buf,"%dh",time); if (strlen(buf)<=width) return buf; time/=24; /* days */ sprintf(buf,"%dd",time); if (strlen(buf)<=width) return buf; time/=7; /* weeks */ sprintf(buf,"%dw",time); return buf; /* this is our last try; if it still doesn't fit, too bad. */ /* :-) I suppose if someone has a SMP version of Linux with a few thousand processors, they could accumulate 18 years of CPU time... */ }/* scale_k(k,width,unit) - interprets k as a count, formats to fit width. if unit is 0, k is a byte count; 1 is a kilobyte count; 2 for megabytes; 3 for gigabytes.*/char *scale_k(int k,int width,int unit) { /* kilobytes, megabytes, gigabytes, too-big-for-int-bytes */ static double scale[]={1024,1024*1024,1024*1024*1024,0}; /* kilo, mega, giga, tera */ static char unitletters[]={'K','M','G','T',0}; static char buf[100]; char *up; double *dp; /* Try successively higher units until it fits */ sprintf(buf,"%d",k); if (strlen(buf)<=width) return buf; for (up=unitletters+unit,dp=scale ; *dp ; ++dp,++up) { sprintf(buf,"%.1f%c",k / *dp,*up); if (strlen(buf)<=width) return buf; sprintf(buf,"%d%c",(int)(k / *dp),*up); if (strlen(buf)<=width) return buf; } /* Give up; give them what we got on our shortest attempt */ return buf;}/* *####################################################################### *#### Routines handling the main top screen: ######## *#### show_task_info, show_procs, show_memory, do_stats ######## *####################################################################### */ /* * Displays infos for a single task */void show_task_info(proc_t *task, int pmem){ int i,j; unsigned int t; char *cmdptr; char tmp[2048], tmp2[2048] = "", tmp3[2048] = "", *p; for (i = 0; i < Numfields; i++) { tmp[0] = 0; switch (pflags[i]) { case P_PID: sprintf(tmp, "%5d ", task->pid); break; case P_PPID: sprintf(tmp, "%5d ", task->ppid); break; case P_EUID: sprintf(tmp, "%4d ", task->euid); break; case P_EUSER: sprintf(tmp, "%-8.8s ", task->euser); break; case P_PCPU: sprintf(tmp, "%4.1f ", (float)task->pcpu / 10); break; case P_LCPU: sprintf(tmp, "%2d ", task->lproc); break; case P_PMEM: sprintf(tmp, "%4.1f ", (float)pmem / 10); break; case P_TTY: { char outbuf[9]; dev_to_tty(outbuf, 8, task->tty, task->pid, ABBREV_DEV); sprintf(tmp, "%-8.8s ", outbuf); } break; case P_PRI: sprintf(tmp, "%3.3s ", scale_k(task->priority, 3, 0)); break; case P_NICE: sprintf(tmp, "%3.3s ", scale_k(task->nice, 3, 0)); break; case P_PAGEIN: sprintf(tmp, "%6.6s ", scale_k(task->maj_flt, 6, 0)); break; case P_TSIZ: sprintf(tmp, "%5.5s ", scale_k(((task->end_code - task->start_code) / 1024), 5, 1)); break; case P_DSIZ: sprintf(tmp, "%5.5s ", scale_k(((task->vsize - task->end_code) / 1024), 5, 1)); break; case P_SIZE: sprintf(tmp, "%5.5s ", scale_k((task->size << CL_pg_shift), 5, 1)); break; case P_TRS: sprintf(tmp, "%4.4s ", scale_k((task->trs << CL_pg_shift), 4, 1)); break; case P_SWAP: sprintf(tmp, "%4.4s ", scale_k(((task->size - task->resident) << CL_pg_shift), 4, 1)); break; case P_SHARE: sprintf(tmp, "%5.5s ", scale_k((task->share << CL_pg_shift), 5, 1)); break; case P_A: sprintf(tmp, "%3.3s ", "NYI"); break; case P_WP: sprintf(tmp, "%3.3s ", "NYI"); break; case P_DT: sprintf(tmp, "%3.3s ", scale_k(task->dt, 3, 0)); break; case P_RSS: /* resident not rss, it seems to be more correct. */ sprintf(tmp, "%4.4s ", scale_k((task->resident << CL_pg_shift), 4, 1)); break; case P_WCHAN: if (!CL_wchan_nout) sprintf(tmp, "%-9.9s ", wchan(task->wchan)); else sprintf(tmp, "%-9lx", task->wchan); break; case P_STAT: sprintf(tmp, "%-4.4s ", status(task)); break; case P_TIME: t = (task->utime + task->stime) / Hertz; if (Cumulative) t += (task->cutime + task->cstime) / Hertz; sprintf(tmp, "%6.6s ", scale_time(t,6)); break; case P_COMMAND: if (!show_cmd && task->cmdline && *(task->cmdline)) { j=0; while(((task->cmdline)[j] != NULL) && (strlen(tmp3)<1020)){/* #if 0 */ /* This is useless? FIXME */ if (j > 0) strcat(tmp3, " ");/* #endif */ strncat(tmp3, (task->cmdline)[j], 1000); j++; } cmdptr = tmp3; } else { cmdptr = task->cmd; } if (strlen(cmdptr) > Maxcmd) cmdptr[Maxcmd - 1] = 0; sprintf(tmp, "%s", cmdptr); tmp3[0]=0; break; case P_FLAGS: sprintf(tmp, "%8lx ", task->flags); break; } strcat(tmp2, tmp); } if (strlen(tmp2) > Cols - 1) tmp2[Cols - 1] = 0; /* take care of cases like: perl -e 'foo bar foo bar foo # end of perl script' */ for (p=tmp2;*p;++p) if (!isgraph(*p)) *p=' '; printf("\n%s", tmp2); PUTP(top_clrtoeol);}/* * This is the real program! Read process info and display it. * One could differentiate options of readproctable2, perhaps it * would be useful to support the PROC_UID and PROC_TTY * as command line options. */void show_procs(void){ static proc_t **p_table=NULL; static int proc_flags; int count; int ActualLines; float elapsed_time; unsigned int main_mem; static int first=0; if (first==0) { proc_flags=PROC_FILLMEM|PROC_FILLCMD|PROC_FILLUSR; if (monpids_index) proc_flags |= PROC_PID; p_table=readproctab2(proc_flags, p_table, monpids); elapsed_time = get_elapsed_time(); do_stats(p_table, elapsed_time, 0); sleep(1); first=1; } if (first && Batch) fputs("\n\n",stdout); /* Display the load averages. */ PUTP(ho); PUTP(md); if (show_loadav) { printf("%s", sprint_uptime()); PUTP(top_clrtoeol); putchar('\n'); } p_table=readproctab2(proc_flags, p_table, monpids); /* Immediately find out the elapsed time for the frame. */ elapsed_time = get_elapsed_time(); /* Display the system stats, calculate percent CPU time * and sort the list. */ do_stats(p_table, elapsed_time,1); /* Display the memory and swap space usage. */ main_mem = show_meminfo(); if (strlen(Header) + 2 > Cols) Header[Cols - 2] = 0; PUTP(mr); fputs(Header, stdout); PUTP(top_clrtoeol); PUTP(me); /* * Finally! Loop through to find the top task, and display it. * Lather, rinse, repeat. */ count = 0; ActualLines = 0; while ((ActualLines < Maxlines) && (p_table[count]->pid!=-1)) { int pmem; char stat; stat = p_table[count]->state; if ( (!Noidle || (stat != 'S' && stat != 'Z')) && ( (CurrUser[0] == '\0') || (!strcmp((char *)CurrUser,p_table[count]->euser) ) ) ) { /* * Show task info. */ pmem = p_table[count]->resident * 1000 / (main_mem / 4); show_task_info(p_table[count], pmem); if (!Batch) ActualLines++; } count++; } PUTP(top_clrtobot); PUTP(tgoto(cm, 0, header_lines - 2)); fflush(stdout);}/* * Finds the current time (in microseconds) and calculates the time * elapsed since the last update. This is essential for computing * percent CPU usage. */float get_elapsed_time(void){ struct timeval time; static struct timeval oldtime; struct timezone timez; float elapsed_time; gettimeofday(&time, &timez); elapsed_time = (time.tv_sec - oldtime.tv_sec) + (float) (time.tv_usec - oldtime.tv_usec) / 1000000.0; oldtime.tv_sec = time.tv_sec; oldtime.tv_usec = time.tv_usec; return (elapsed_time);}/* * Reads the memory info and displays it. Returns the total memory * available, for use in percent memory usage calculations. */unsigned show_meminfo(void){ unsigned long long **mem; if (!(mem = meminfo()) || /* read+parse /proc/meminfo */ mem[meminfo_main][meminfo_total] == 0) { /* cannot normalize mem usage */ fprintf(stderr, "Cannot get size of memory from /proc/meminfo\n"); error_end(1); } if (show_memory) { printf("Mem: %7LdK av, %7LdK used, %7LdK free, %7LdK shrd, %7LdK buff", mem[meminfo_main][meminfo_total] >> 10, mem[meminfo_main][meminfo_used] >> 10, mem[meminfo_main][meminfo_free] >> 10, mem[meminfo_main][meminfo_shared] >> 10, mem[meminfo_main][meminfo_buffers] >> 10); PUTP(top_clrtoeol); putchar('\n'); printf("Swap: %7LdK av, %7LdK used, %7LdK free %7LdK cached", mem[meminfo_swap][meminfo_total] >> 10, mem[meminfo_swap][meminfo_used] >> 10, mem[meminfo_swap][meminfo_free] >> 10, mem[meminfo_total][meminfo_cached] >> 10); PUTP(top_clrtoeol); putchar('\n'); } PUTP(me); PUTP(top_clrtoeol); putchar('\n'); return mem[meminfo_main][meminfo_total] >> 10;}/* * Calculates the number of tasks in each state (running, sleeping, etc.). * Calculates the CPU time in each state (system, user, nice, etc). * Calculates percent cpu usage for each task. */void do_stats(proc_t** p, float elapsed_time, int pass){ proc_t *this; int index, total_time, cpumap, i, n = 0; int sleeping = 0, stopped = 0, zombie = 0, running = 0; unsigned long system_ticks = 0, user_ticks = 0, nice_ticks = 0, idle_ticks; static int prev_count = 0; int stime, utime; /* start with one 4K page as a reasonable allocate size */ static int save_history_size = sizeof(struct save_hist) * 204; static struct save_hist *save_history; struct save_hist *New_save_hist; static int *s_ticks_o = NULL, *u_ticks_o = NULL, *n_ticks_o = NULL, *i_ticks_o = NULL; int s_ticks, u_ticks, n_ticks, i_ticks, t_ticks; char str[128]; FILE *file; if (!save_history) save_history = xcalloc(NULL, save_history_size); New_save_hist = xcalloc(NULL, save_history_size); if(s_ticks_o == NULL) { s_ticks_o = (int *)malloc(nr_cpu * sizeof(int)); u_ticks_o = (int *)malloc(nr_cpu * sizeof(int)); n_ticks_o = (int *)malloc(nr_cpu * sizeof(int)); i_ticks_o = (int *)malloc(nr_cpu * sizeof(int)); } idle_ticks = 1000 * nr_cpu; /* * Make a pass through the data to get stats. */ index = 0; while (p[n]->pid != -1) { this = p[n]; switch (this->state) { case 'S': case 'D': sleeping++; break; case 'T': stopped++; break; case 'Z': zombie++; break; case 'R': running++; break; default: /* Don't know how to handle this one. */ break; } /* * Calculate time in this process. Time is sum of user time * (utime) plus system time (stime). */ total_time = this->utime + this->stime; if (index * sizeof(struct save_hist) >= save_history_size) { save_history_size *= 2; save_history = xrealloc(save_history, save_history_size); New_save_hist = xrealloc(New_save_hist, save_history_size); } New_save_hist[index].ticks = total_time; New_save_hist[index].pid = this->pid; stime = this->stime; utime = this->utime; New_save_hist[index].stime = stime; New_save_hist[index].utime = utime; /* find matching entry from previous pass */ for (i = 0; i < prev_count; i++) { if (save_history[i].pid == this->pid) { total_time -= save_history[i].ticks; stime -= save_history[i].stime; utime -= save_history[i].utime; i = prev_count; } } /* * Calculate percent cpu time for this task. */ this->pcpu = (total_time * 10 * 100/Hertz) / elapsed_time; if (this->pcpu > 999) this->pcpu = 999; /* * Calculate time in idle, system, user and niced tasks. */ idle_ticks -= this->pcpu; system_ticks += stime; user_ticks += utime; if (this->nice > 0) nice_ticks += this->pcpu; /* * If in Sun-mode, adjust cpu percentage not only for * the cpu the process is running on, but for all cpu together. */ if(!Irixmode) { this->pcpu /= nr_cpu; } index++; n++; } if (idle_ticks < 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -