📄 top.c
字号:
idle_ticks = 0; system_ticks = (system_ticks * 10 * 100/Hertz) / elapsed_time; user_ticks = (user_ticks * 10 * 100/Hertz) / elapsed_time; /* * Display stats. */ if (pass > 0 && show_stats) { printf("%d processes: %d sleeping, %d running, %d zombie, " "%d stopped", n, sleeping, running, zombie, stopped); PUTP(top_clrtoeol); putchar('\n'); if (nr_cpu == 1 || CPU_states) { /* BEGIN EXPERIMENTAL CODE */ /* Throw out the calculation above... TODO: remove calculation. */ four_cpu_numbers(&user_ticks,&nice_ticks,&system_ticks,&idle_ticks); do{ unsigned long sum; sum = user_ticks+nice_ticks+system_ticks+idle_ticks; user_ticks = (user_ticks * 1000) / sum; system_ticks = (system_ticks * 1000) / sum; nice_ticks = (nice_ticks * 1000) / sum; idle_ticks = (idle_ticks * 1000) / sum; }while(0); /* END EXPERIMENTAL CODE */ if (Irixmode) { user_ticks *= nr_cpu; system_ticks *= nr_cpu; nice_ticks *= nr_cpu; idle_ticks *= nr_cpu; } printf("CPU states:" " %2ld.%ld%% user, %2ld.%ld%% system," " %2ld.%ld%% nice, %2ld.%ld%% idle", user_ticks / 10UL, user_ticks % 10UL, system_ticks / 10UL, system_ticks % 10UL, nice_ticks / 10UL, nice_ticks % 10UL, idle_ticks / 10UL, idle_ticks % 10UL); PUTP(top_clrtoeol); putchar('\n'); } /* * Calculate stats for all cpus */ if(nr_cpu > 1) { file = fopen("/proc/stat", "r"); if(file == NULL) { fprintf(stderr, "fopen failed on /proc/stat\n"); } else { /* Skip the total CPU states. */ if(fgets(str, 128, file) == NULL) { fprintf(stderr, "fgets failed on /proc/stat\n"); } else { for(i = 0; i < nr_cpu; i++) { if(fscanf(file, "cpu%*d %d %d %d %d\n", &u_ticks, &n_ticks, &s_ticks, &i_ticks) != 4) { fprintf(stderr, "fscanf failed on /proc/stat for cpu %d\n", i); break; } else { t_ticks = (u_ticks + s_ticks + i_ticks + n_ticks) - (u_ticks_o[i] + s_ticks_o[i] + i_ticks_o[i] + n_ticks_o[i]); if (Irixmode) cpumap=i; else cpumap=cpu_mapping[i]; printf ("CPU%d states: %2d.%-d%% user, %2d.%-d%% system," " %2d.%-d%% nice, %2d.%-d%% idle", cpumap, (u_ticks - u_ticks_o[i] + n_ticks - n_ticks_o[i]) * 100 / t_ticks, (u_ticks - u_ticks_o[i]) * 100 % t_ticks / 100, (s_ticks - s_ticks_o[i]) * 100 / t_ticks, (s_ticks - s_ticks_o[i]) * 100 % t_ticks / 100, (n_ticks - n_ticks_o[i]) * 100 / t_ticks, (n_ticks - n_ticks_o[i]) * 100 % t_ticks / 100, (i_ticks - i_ticks_o[i]) * 100 / t_ticks, (i_ticks - i_ticks_o[i]) * 100 % t_ticks / 100); s_ticks_o[i] = s_ticks; u_ticks_o[i] = u_ticks; n_ticks_o[i] = n_ticks; i_ticks_o[i] = i_ticks; PUTP (top_clrtoeol); putchar ('\n'); } } } fclose(file); } } } else { /* * During the first pass, get the information for the * different CPUs. */ if(nr_cpu > 1) { file = fopen("/proc/stat", "r"); if(file == NULL) { puts("open"); } if(fgets(str, 128, file) == NULL) { fprintf(stderr, "fgets failed on /proc/stat\n"); } for(i = 0; i < nr_cpu; i++) { if(fscanf(file, "cpu%*d %d %d %d %d\n", &u_ticks_o[i], &n_ticks_o[i], &s_ticks_o[i], &i_ticks_o[i]) != 4) { fprintf(stderr, "fscanf failed on /proc/stat for cpu %d\n", i); } } fclose(file); } } /* * Save this frame's information. */ for (i = 0; i < n; i++) { /* copy the relevant info for the next pass */ save_history[i].pid = New_save_hist[i].pid; save_history[i].ticks = New_save_hist[i].ticks; save_history[i].stime = New_save_hist[i].stime; save_history[i].utime = New_save_hist[i].utime; } free(New_save_hist); prev_count = n; qsort(p, n, sizeof(proc_t*), (void*)mult_lvl_cmp);}/* * Process keyboard input during the main loop */void do_key(char c){ int numinput, i; char rcfile[MAXNAMELEN]; FILE *fp; /* * First the commands which don't require a terminal mode switch. */ if (c == 'q') end(0); else if (c == ' ') return; else if (c == 12) { clear_screen(); return; } else if (c == 'I') { Irixmode=(Irixmode) ? 0 : 1; return; } /* * Switch the terminal to normal mode. (Will the original * attributes always be normal? Does it matter? I suppose the * shell will be set up the way the user wants it.) */ if (!Batch) tcsetattr(0, TCSANOW, &Savetty); /* * Handle the rest of the commands. */ switch (c) { case '?': case 'h': PUTP(cl); PUTP(ho); putchar('\n'); PUTP(mr); printf("Proc-Top Revision 1.2"); PUTP(me); putchar('\n'); printf("Secure mode "); PUTP(md); fputs(Secure ? "on" : "off", stdout); PUTP(me); fputs("; cumulative mode ", stdout); PUTP(md); fputs(Cumulative ? "on" : "off", stdout); PUTP(me); fputs("; noidle mode ", stdout); PUTP(md); fputs(Noidle ? "on" : "off", stdout); PUTP(me); fputs("\n\n", stdout); printf("%s\n\nPress any key to continue", Secure ? SECURE_HELP_SCREEN : HELP_SCREEN); if (!Batch) tcsetattr(0, TCSANOW, &Rawtty); (void) getchar(); break; case 'i': Noidle = !Noidle; SHOWMESSAGE(("No-idle mode %s", Noidle ? "on" : "off")); break; case 'u': SHOWMESSAGE(("Which User (Blank for All): ")); strcpy(CurrUser,getstr()); break; case 'k': if (Secure) SHOWMESSAGE(("\aCan't kill in secure mode")); else { int pid, signal; PUTP(md); SHOWMESSAGE(("PID to kill: ")); pid = getint(); if (pid == BAD_INPUT) break; PUTP(top_clrtoeol); SHOWMESSAGE(("Kill PID %d with signal [15]: ", pid)); PUTP(me); signal = getsig(); if (signal == -1) signal = SIGTERM; if (kill(pid, signal)) SHOWMESSAGE(("\aKill of PID %d with %d failed: %s", pid, signal, strerror(errno))); } break; case 'l': SHOWMESSAGE(("Display load average %s", !show_loadav ? "on" : "off")); if (show_loadav) { show_loadav = 0; header_lines--; } else { show_loadav = 1; header_lines++; } Numfields = make_header(); break; case 'm': SHOWMESSAGE(("Display memory information %s", !show_memory ? "on" : "off")); if (show_memory) { show_memory = 0; header_lines -= 2; } else { show_memory = 1; header_lines += 2; } Numfields = make_header(); break; case 'M': SHOWMESSAGE(("Sort by memory usage")); sort_type = S_MEM; reset_sort_options(); register_sort_function(-1, (cmp_t)mem_sort); break; case 'n': case '#': printf("Processes to display (0 for unlimited): "); numinput = getint(); if (numinput != BAD_INPUT) { Display_procs = numinput; window_size(0); } break; case 'r': if (Secure) SHOWMESSAGE(("\aCan't renice in secure mode")); else { int pid, val; printf("PID to renice: "); pid = getint(); if (pid == BAD_INPUT) break; PUTP(tgoto(cm, 0, header_lines - 2)); PUTP(top_clrtoeol); printf("Renice PID %d to value: ", pid); val = getint(); if (val == BAD_INPUT) val = 10; if (setpriority(PRIO_PROCESS, pid, val)) SHOWMESSAGE(("\aRenice of PID %d to %d failed: %s", pid, val, strerror(errno))); } break; case 'P': SHOWMESSAGE(("Sort by CPU usage")); sort_type = S_PCPU; reset_sort_options(); register_sort_function(-1, (cmp_t)pcpu_sort); break; case 'A': SHOWMESSAGE(("Sort by age")); sort_type = S_AGE; reset_sort_options(); register_sort_function(-1, (cmp_t)age_sort); break; case 'N': SHOWMESSAGE(("Sort numerically by pid")); sort_type = S_NONE; reset_sort_options(); break; case 'c': show_cmd = !show_cmd; SHOWMESSAGE(("Show %s", show_cmd ? "command names" : "command line")); break; case 'S': Cumulative = !Cumulative; SHOWMESSAGE(("Cumulative mode %s", Cumulative ? "on" : "off")); if (Cumulative) headers[22][1] = 'C'; else headers[22][1] = ' '; Numfields = make_header(); break; case 's': if (Secure) SHOWMESSAGE(("\aCan't change delay in secure mode")); else { double tmp; printf("Delay between updates: "); tmp = getfloat(); if (!(tmp < 0)) Sleeptime = tmp; } break; case 't': SHOWMESSAGE(("Display summary information %s", !show_stats ? "on" : "off")); if (show_stats) { show_stats = 0; header_lines -= 2; } else { show_stats = 1; header_lines += 2; } Numfields = make_header(); break; case 'T': SHOWMESSAGE(("Sort by %stime", Cumulative ? "cumulative " : "")); sort_type = S_TIME; reset_sort_options(); register_sort_function( -1, (cmp_t)time_sort); break; case 'f': case 'F': change_fields(); break; case 'o': case 'O': change_order(); break; case 'W': if (getenv("HOME")) { strcpy(rcfile, getenv("HOME")); strcat(rcfile, "/"); strcat(rcfile, RCFILE); fp = fopen(rcfile, "w"); if (fp != NULL) { fprintf(fp, "%s\n", Fields); i = (int) Sleeptime; if (i < 2) i = 2; if (i > 9) i = 9; fprintf(fp, "%d", i); if (Secure) fprintf(fp, "%c", 's'); if (Cumulative) fprintf(fp, "%c", 'S'); if (!show_cmd) fprintf(fp, "%c", 'c'); if (Noidle) fprintf(fp, "%c", 'i'); if (!show_memory) fprintf(fp, "%c", 'm'); if (!show_loadav) fprintf(fp, "%c", 'l'); if (!show_stats) fprintf(fp, "%c", 't'); if (!Irixmode) fprintf(fp, "%c", 'I'); fprintf(fp, "\n"); fclose(fp); SHOWMESSAGE(("Wrote configuration to %s", rcfile)); } else { SHOWMESSAGE(("Couldn't open %s", rcfile)); } } else { SHOWMESSAGE(("Couldn't get $HOME -- not saving")); } break; default: SHOWMESSAGE(("\aUnknown command `%c' -- hit `h' for help", c)); } /* * Return to raw mode. */ if (!Batch) tcsetattr(0, TCSANOW, &Rawtty); return;}/*##################################################################### *####### A readproctable function that uses already allocated ##### *####### table entries. ##### *##################################################################### */#define Do(x) (flags & PROC_ ## x)proc_t** readproctab2(int flags, proc_t** tab, ...) { PROCTAB* PT = NULL; static proc_t *buff; int n = 0; static int len = 0; va_list ap; va_start(ap, tab); /* pass through args to openproc */ if (Do(UID)) { /* temporary variables to ensure that va_arg() instances * are called in the right order */ uid_t* u; int i; u = va_arg(ap, uid_t*); i = va_arg(ap, int); PT = openproc(flags, u, i); } else if (Do(PID)) { PT = openproc(flags, va_arg(ap, void*)); /* assume ptr sizes same */ /* work around a bug in openproc() */ PT->procfs = NULL; /* share some process time, since we skipped opendir("/proc") */ usleep (50*1000); } else if (Do(TTY) || Do(STAT)) PT = openproc(flags, va_arg(ap, void*)); /* assume ptr sizes same */ else PT = openproc(flags); va_end(ap); buff = (proc_t *) 1; while (n<len && buff) { /* read table: (i) already allocated chunks */ if (tab[n]->cmdline) { free((void*)*tab[n]->cmdline); tab[n]->cmdline = NULL; } buff = readproc(PT, tab[n]); if (buff) n++; } if (buff) { do { /* (ii) not yet allocated chunks */ tab = xrealloc(tab, (n+1)*sizeof(proc_t*));/* realloc as we go, using */ buff = readproc(PT, NULL); /* final null to terminate */ if(buff) tab[n]=buff; len++; n++; } while (buff); /* stop when NULL reached */ tab[n-1] = xcalloc(NULL, sizeof (proc_t)); tab[n-1]->pid=-1; /* Mark end of Table */ } else { if (n == len) { tab = xrealloc(tab, (n+1)*sizeof(proc_t*)); tab[n] = xcalloc(NULL, sizeof (proc_t)); len++; } tab[n]->pid=-1; /* Use this instead of NULL when not at the end of */ } /* the allocated space */ closeproc(PT); return tab;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -