📄 top.c
字号:
exit(1); } cp++; } breakargv: } if (nr_cpu > 1 && CPU_states) header_lines++; setup_terminal(); window_size(0); /* * Set up signal handlers. */ sact.sa_handler = end; sact.sa_flags = 0; sigemptyset(&sact.sa_mask); sigaction(SIGHUP, &sact, NULL); sigaction(SIGINT, &sact, NULL); sigaction(SIGQUIT, &sact, NULL); sact.sa_handler = stop; sact.sa_flags = SA_RESTART; sigaction(SIGTSTP, &sact, NULL); sact.sa_handler = window_size; sigaction(SIGWINCH, &sact, NULL); sigaction(SIGCONT, &sact, NULL); /* loop, collecting process info and sleeping */ while (1) { if (Loops > 0) Loops--; /* display the tasks */ show_procs(); /* sleep & wait for keyboard input */ if (Loops == 0) end(0); if (!Batch) { tv.tv_sec = Sleeptime; tv.tv_usec = (Sleeptime - (int) Sleeptime) * 1000000; FD_ZERO(&in); FD_SET(0, &in); if (select(1, &in, 0, 0, &tv) > 0 && read(0, &c, 1) == 1) do_key(c); } else { sleep(Sleeptime); } }}/*####################################################################### *#### Signal handled routines: error_end, end, stop, window_size ### *#### Small utilities: make_header, getstr, getint, getfloat, getsig ### *####################################################################### */ /* * end when exiting with an error. */void error_end(int rno){ if (psdbsucc) close_psdb(); if (!Batch) tcsetattr(0, TCSAFLUSH, &Savetty); PUTP(tgoto(cm, 0, Lines - 1)); fputs("\r\n", stdout); exit(rno);}/* * Normal end of execution. */void end(int signo){ if (psdbsucc) close_psdb(); if (!Batch) tcsetattr(0, TCSAFLUSH, &Savetty); PUTP(tgoto(cm, 0, Lines - 1)); fputs("\r\n", stdout); exit(0);}/* * SIGTSTP catcher. */void stop(int signo){ /* Reset terminal. */ if (!Batch) tcsetattr(0, TCSAFLUSH, &Savetty); PUTP(tgoto(cm, 0, Lines - 3)); fflush(stdout); raise(SIGSTOP); /* Later... */ if (!Batch) tcsetattr (0, TCSAFLUSH, &Rawtty);}/* * Reads the window size and clear the window. This is called on setup, * and also catches SIGWINCHs, and adjusts Maxlines. Basically, this is * the central place for window size stuff. */void window_size(int signo){ struct winsize ws; if((ioctl(1, TIOCGWINSZ, &ws) != -1) && (ws.ws_col>73) && (ws.ws_row>7)){ Cols = ws.ws_col; Lines = ws.ws_row; }else{ Cols = tgetnum("co"); Lines = tgetnum("li"); } if (!Batch) clear_screen(); /* * calculate header size, length of cmdline field ... */ Numfields = make_header();}/* * this prints a possible message from open_psdb_message */static void top_message(const char *format, ...) { va_list arg; int n; char buffer[512]; va_start (arg, format); n = vsnprintf (buffer, 512, format, arg); va_end (arg); if (n > -1 && n < 512) SHOWMESSAGE(("%s", buffer));}/* * this adjusts the lines needed for the header to the current value */int make_header(void){ int i, j; j = 0; for (i = 0; i < strlen(Fields); i++) { if (Fields[i] < 'a') { pflags[j++] = Fields[i] - 'A'; if (Fields[i] == 'U' && CL_wchan_nout == -1) { CL_wchan_nout = 0; /* for correct handling of WCHAN fields, we have to do distinguish * between kernel versions */ /* get kernel symbol table, if needed */ if (open_psdb_message(NULL, top_message)) { CL_wchan_nout = 1; } else { psdbsucc = 1; } } } } strcpy(Header, ""); for (i = 0; i < j; i++) strcat(Header, headers[pflags[i]]); /* readjust window size ... */ Maxcmd = Cols - strlen(Header) + 7; Maxlines = Display_procs ? Display_procs : Lines - header_lines; if (Maxlines > Lines - header_lines) Maxlines = Lines - header_lines; return (j);}/* * Get a string from the user; the base of getint(), et al. This really * ought to handle long input lines and errors better. NB: The pointer * returned is a statically allocated buffer, so don't expect it to * persist between calls. */char *getstr(void){ static char line[BUFSIZ]; /* BUFSIZ from <stdio.h>; arbitrary */ int i = 0; /* Must make sure that buffered IO doesn't kill us. */ fflush(stdout); fflush(stdin); /* Not POSIX but ok */ do { read(STDIN_FILENO, &line[i], 1); } while (line[i++] != '\n' && i < sizeof(line)); line[--i] = 0; return (line);}/* * Get an integer from the user. Display an error message and return BAD_INPUT * if it's invalid; else return the number. */int getint(void){ char *line; int i; int r; line = getstr(); for (i = 0; line[i]; i++) { if (!isdigit(line[i]) && line[i] != '-') { SHOWMESSAGE(("That's not a number!")); return (BAD_INPUT); } } /* An empty line is a legal error (hah!). */ if (!line[0]) return (BAD_INPUT); sscanf(line, "%d", &r); return (r);}/* * Get a float from the user. Just like getint(). */float getfloat(void){ char *line; int i; float r; line = getstr(); for (i = 0; line[i]; i++) { if (!isdigit(line[i]) && line[i] != '.' && line[i] != '-') { SHOWMESSAGE(("That's not a float!")); return (BAD_INPUT); } } /* An empty line is a legal error (hah!). */ if (!line[0]) return (BAD_INPUT); sscanf(line, "%f", &r); return (r);}/* * Get a signal number or name from the user. Return the number, or -1 * on error. */int getsig(void){ char *line; /* This is easy. */ line = getstr(); return (get_signal2(line));}/*####################################################################### *#### Routine for sorting on used time, resident memory and %CPU ##### *#### It would be easy to include full sorting capability as in ##### *#### ps, but I think there is no real use for something that ##### *#### complicated. Using register_sort_function or parse_sort_opt ##### *#### you just have to do the natural thing and it will work. ##### *####################################################################### */int time_sort (proc_t **P, proc_t **Q){ if (Cumulative) { if( ((*P)->cutime + (*P)->cstime + (*P)->utime + (*P)->stime) < ((*Q)->cutime + (*Q)->cstime + (*Q)->utime + (*Q)->stime) ) return -1; if( ((*P)->cutime + (*P)->cstime + (*P)->utime + (*P)->stime) > ((*Q)->cutime + (*Q)->cstime + (*Q)->utime + (*Q)->stime) ) return 1; } else { if( ((*P)->utime + (*P)->stime) < ((*Q)->utime + (*Q)->stime)) return -1; if( ((*P)->utime + (*P)->stime) > ((*Q)->utime + (*Q)->stime)) return 1; } return 0;}int pcpu_sort (proc_t **P, proc_t **Q){ if( (*P)->pcpu < (*Q)->pcpu ) return -1; if( (*P)->pcpu > (*Q)->pcpu ) return 1; return 0;}int mem_sort (proc_t **P, proc_t **Q){ if( (*P)->resident < (*Q)->resident ) return -1; if( (*P)->resident > (*Q)->resident ) return 1; return 0;}int age_sort (proc_t **P, proc_t **Q){ if( (*P)->start_time < (*Q)->start_time ) return -1; if( (*P)->start_time > (*Q)->start_time ) return 1; return 0;}/*####################################################################### *#### Routines handling the field selection/ordering screens: ######## *#### show_fields, change_order, change_fields ######## *####################################################################### */ /* * Display the specification line of all fields. Upper case indicates * a displayed field, display order is according to the order of the * letters. A short description of each field is shown as well. * The description of a displayed field is marked by a leading * asterisk (*). */void show_fields(void){ int i, row, col; char *p; clear_screen(); PUTP(tgoto(cm, 3, 0)); printf("Current Field Order: %s\n", Fields); for (i = 0; i < sizeof headers / sizeof headers[0]; ++i) { row = i % (Lines - 3) + 3; col = i / (Lines - 3) * 40; PUTP(tgoto(cm, col, row)); for (p = headers[i]; *p == ' '; ++p); printf("%c %c: %-10s = %s", (strchr(Fields, i + 'A') != NULL) ? '*' : ' ', i + 'A', p, headers2[i]); }}/* * change order of displayed fields */void change_order(void){ char c, ch, *p; int i; show_fields(); for (;;) { PUTP(tgoto(cm, 0, 0)); PUTP(top_clrtoeol); PUTP(tgoto(cm, 3, 0)); PUTP(mr); printf("Current Field Order: %s", Fields); PUTP(me); putchar('\n'); PUTP(tgoto(cm, 0, 1)); printf("Upper case characters move a field to the left, lower case to the right"); fflush(stdout); if (!Batch) { /* should always be true, but... */ tcsetattr(0, TCSAFLUSH, &Rawtty); read(0, &c, 1); tcsetattr(0, TCSAFLUSH, &Savetty); } i = toupper(c) - 'A'; if ((p = strchr(Fields, i + 'A')) != NULL) { if (isupper(c)) p--; if ((p[1] != '\0') && (p >= Fields)) { ch = p[0]; p[0] = p[1]; p[1] = ch; } } else if ((p = strchr(Fields, i + 'a')) != NULL) { if (isupper(c)) p--; if ((p[1] != '\0') && (p >= Fields)) { ch = p[0]; p[0] = p[1]; p[1] = ch; } } else { break; } } Numfields = make_header();}/* * toggle displayed fields */void change_fields(void){ int i, changed = 0; int row, col; char c, *p; char tmp[2] = " "; show_fields(); for (;;) { PUTP(tgoto(cm, 0, 0)); PUTP(top_clrtoeol); PUTP(tgoto(cm, 3, 0)); PUTP(mr); printf("Current Field Order: %s", Fields); PUTP(me); putchar('\n'); PUTP(tgoto(cm, 0, 1)); printf("Toggle fields with a-x, any other key to return: "); fflush(stdout); if (!Batch) { /* should always be true, but... */ tcsetattr(0, TCSAFLUSH, &Rawtty); read(0, &c, 1); tcsetattr(0, TCSAFLUSH, &Savetty); } i = toupper(c) - 'A'; if (i >= 0 && i < sizeof headers / sizeof headers[0]) { row = i % (Lines - 3) + 3; col = i / (Lines - 3) * 40; PUTP(tgoto(cm, col, row)); if ((p = strchr(Fields, i + 'A')) != NULL) { /* deselect Field */ *p = i + 'a'; putchar(' '); } else if ((p = strchr(Fields, i + 'a')) != NULL) { /* select previously */ *p = i + 'A'; /* deselected field */ putchar('*'); } else { /* select new field */ tmp[0] = i + 'A'; strcat(Fields, tmp); putchar('*'); } changed = 1; fflush(stdout); } else break; } if (changed) Numfields = make_header();}/* Do the scaling stuff scale_time(time,width) - interprets time in seconds, formats it to fit width Both return pointer to static char*.*/char *scale_time(int time,int width) { static char buf[100]; /* Try successively higher units until it fits */ sprintf(buf,"%d:%02d",time/60,time%60); /* minutes:seconds */ if (strlen(buf)<=width) return buf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -