⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 top.c

📁 Linux下进程监控相关源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * top.c              - show top CPU processes * * Copyright (c) 1992 Branko Lankester * Copyright (c) 1992 Roger Binns * Copyright (c) 1997 Michael K. Johnson * * Snarfed and HEAVILY modified in december 1992 for procps * by Michael K. Johnson, johnsonm@sunsite.unc.edu. * * Modified Michael K. Johnson's ps to make it a top program. * Also borrowed elements of Roger Binns kmem based top program. * Changes made by Robert J. Nation (nation@rocket.sanders.lockheed.com) * 1/93 * * Modified by Michael K. Johnson to be more efficient in cpu use * 2/21/93 * * Changed top line to use uptime for the load average.  Also * added SIGTSTP handling.  J. Cowley, 19 Mar 1993. * * Modified quite a bit by Michael Shields (mjshield@nyx.cs.du.edu) * 1994/04/02.  Secure mode added.  "d" option added.  Argument parsing * improved.  Switched order of tick display to user, system, nice, idle, * because it makes more sense that way.  Style regularized (to K&R, * more or less).  Cleaned up much throughout.  Added cumulative mode. * Help screen improved. * * Fixed kill buglet brought to my attention by Rob Hooft. * Problem was mixing of stdio and read()/write().  Added * getnum() to solve problem. * 12/30/93 Michael K. Johnson * * Added toggling output of idle processes via 'i' key. * 3/29/94 Gregory K. Nickonov * * Fixed buglet where rawmode wasn't getting restored. * Added defaults for signal to send and nice value to use. * 5/4/94 Jon Tombs. * * Modified 1994/04/25 Michael Shields <mjshield@nyx.cs.du.edu> * Merged previous changes to 0.8 into 0.95. * Allowed the use of symbolic names (e.g., "HUP") for signal input. * Rewrote getnum() into getstr(), getint(), getsig(), etc. *  * Modified 1995  Helmut Geyer <Helmut.Geyer@iwr.uni-heidelberg.de>  * added kmem top functionality (configurable fields) * configurable order of process display * Added options for dis/enabling uptime, statistics, and memory info. * fixed minor bugs for ELF systems (e.g. SIZE, RSS fields) * * Modified 1996/05/18 Helmut Geyer <Helmut.Geyer@iwr.uni-heidelberg.de> * Use of new interface and general cleanup. The code should be far more * readable than before. * * Modified 1996/06/25 Zygo Blaxell <zblaxell@ultratech.net> * Added field scaling code for programs that run more than two hours or * take up more than 100 megs.  We have lots of both on our production line. * * Modified 1998/02/21 Kirk Bauer <kirk@kaybee.org> * Added the 'u' option to display only a selected user... plus it will * take into account that not all 20 top processes are actually shown, * so it can fit more onto the screen.  I think this may help the * 'don't show idle' mode, but I'm not sure. * * Modified 1997/07/27 & 1999/01/27 Tim Janik <timj@gtk.org> * added `-p' option to display specific process ids. * process sorting is by default disabled in this case. * added `N' and `A' keys to sort the tasks Numerically by pid or * sort them by Age (newest first). * * Modified 1999/10/22 Tim Janik <timj@gtk.org> * miscellaneous minor fixes, including "usage: ..." output for * unrecognized options. * * Modified 2000/02/07 Jakub Jelinek <jakub@redhat.com> * Only load System.map when we are going to display WCHAN. * Show possible error messages from that load using SHOWMESSAGE. * * Modified 2000/07/10 Michael K. Johnson <johnsonm@redhat.com> * Integrated a patch to display SMP information. */#include <errno.h>#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <libintl.h>#include <time.h>#include <sys/ioctl.h>#include <pwd.h>#include <termcap.h>#include <termios.h>#include <signal.h>#include <sys/time.h>#include <sys/resource.h>#include <ctype.h>#include <setjmp.h>#include <stdarg.h>#include <sys/param.h>#include "proc/sysinfo.h"#include "proc/procps.h"#include "proc/whattime.h"#include "proc/signals.h"#include "proc/version.h"#include "proc/readproc.h"#include "proc/status.h"#include "proc/devname.h"/* these should be in the readproc.h header or in the procps.h header */typedef int (*cmp_t)(void*,void*);extern void reset_sort_options (void);extern int parse_sort_opt(char* opt);extern void register_sort_function (int dir, cmp_t func);#define PUTP(x) (tputs(x,1,putchar))#define BAD_INPUT -30#include "top.h"  /* new header for top specific things */static int *cpu_mapping;static int nr_cpu;/*####################################################################### *####  Startup routines: parse_options, get_options,      ############## *####                    setup_terminal and main          ############## *####################################################################### */      /*       * parse the options string as read from the config file(s).       * if top is in secure mode, disallow changing of the delay time between       * screen updates.       */void parse_options(char *Options, int secure){    int i;    for (i = 0; i < strlen(Options); i++) {	switch (Options[i]) {	  case '2':	  case '3':	  case '4':	  case '5':	  case '6':	  case '7':	  case '8':	  case '9':	    if (!secure)		Sleeptime = (float) Options[i] - '0';	    break;	  case 'S':	    Cumulative = 1;	    headers[22][1] = 'C';	    break;	  case 's':	    Secure = 1;	    break;	  case 'i':	    Noidle = 1;	    break;	  case 'm':	    show_memory = 0;	    header_lines -= 2;	    break;	  case 'M':	    sort_type = S_MEM;	    reset_sort_options();	    register_sort_function( -1, (cmp_t)mem_sort);	    break;	  case 'l':	    show_loadav = 0;	    header_lines -= 1;	    break;	  case 'P':	    sort_type = S_PCPU;	    reset_sort_options();	    register_sort_function( -1, (cmp_t)pcpu_sort);	    break;	  case 'N':	    sort_type = S_NONE;	    reset_sort_options();	    break;	  case 'A':	    sort_type = S_AGE;	    reset_sort_options();	    register_sort_function( -1, (cmp_t)age_sort);	    break;	  case 't':	    show_stats = 0;	    header_lines -= 2;	    break;	  case 'T':	    sort_type = S_TIME;	    reset_sort_options();	    register_sort_function( -1, (cmp_t)time_sort);	    break;	  case 'c':	    show_cmd = 0;	    break;	  case '\n':	    break;	  case 'I':	    Irixmode = 0;	    break;	  default:	    fprintf(stderr, "Wrong configuration option %c\n", i);	    exit(1);	    break;	}    }}/*  * Read the configuration file(s). There are two files, once SYS_TOPRC  * which should only contain the secure switch and a sleeptime * value iff ordinary users are to use top in secure mode only. *  * The other file is $HOME/RCFILE.  * The configuration file should contain two lines (any of which may be *  empty). The first line specifies the fields that are to be displayed * in the order you want them to. Uppercase letters specify fields  * displayed by default, lowercase letters specify fields not shown by * default. The order of the letters in this line corresponds to the  * order of the displayed fileds. * * all Options but 'q' can be read from this config file * The delay time option syntax differs from the commandline syntax: *   only integer values between 2 and 9 seconds are recognized *   (this is for standard configuration, so I think this should do). * * usually this file is not edited by hand, but written from top using * the 'W' command.  */void get_options(void){    FILE *fp;    char *pt;    char rcfile[MAXNAMELEN];    char Options[256] = "";    int i;    nr_cpu = sysconf (_SC_NPROCESSORS_ONLN);    cpu_mapping = (int *) xmalloc (sizeof (int) * nr_cpu);    /* read cpuname */    for (i=0; i< nr_cpu; i++) cpu_mapping[i]=i;    header_lines = 6 + nr_cpu;    strcpy(rcfile, SYS_TOPRC);    fp = fopen(rcfile, "r");    if (fp != NULL) {	fgets(Options, 254, fp);	fclose(fp);    }    parse_options(Options, 0);    strcpy(Options, "");    if (getenv("HOME")) {	strcpy(rcfile, getenv("HOME"));	strcat(rcfile, "/");    }    strcat(rcfile, RCFILE);    fp = fopen(rcfile, "r");    if (fp == NULL) {	strcpy(Fields, DEFAULT_SHOW);    } else {	if (fgets(Fields, 254, fp) != NULL) {	    pt = strchr(Fields, '\n');	    if (pt) *pt = 0;	}	fgets(Options, 254, fp);	fclose(fp);    }    parse_options(Options, getuid()? Secure : 0);}/*     * Set up the terminal attributes.     */void setup_terminal(void){    char *termtype;    struct termios newtty;    if (!Batch)    	termtype = getenv("TERM");    else 	termtype = "dumb";    if (!termtype) {	/* In theory, $TERM should never not be set, but in practice,	   some gettys don't.  Fortunately, vt100 is nearly always	   correct (or pretty close). */	termtype = "VT100";	/* fprintf(stderr, PROGNAME ": $TERM not set\n"); */	/* exit(1); */    }    /*     * Get termcap entries and window size.     */    if(tgetent(NULL, termtype) != 1) {       fprintf(stderr, PROGNAME ": Unknown terminal \"%s\" in $TERM\n",               termtype);       exit(1);    }    cm = tgetstr("cm", 0);    top_clrtobot = tgetstr("cd", 0);    cl = tgetstr("cl", 0);    top_clrtoeol = tgetstr("ce", 0);    ho = tgetstr("ho", 0);    md = tgetstr("md", 0);    mr = tgetstr("mr", 0);    me = tgetstr("me", 0);    if (Batch) return; /* the rest doesn't apply to batch mode */    if (tcgetattr(0, &Savetty) == -1) {        perror(PROGNAME ": tcgetattr() failed");	error_end(errno);    }    newtty = Savetty;    newtty.c_lflag &= ~ICANON;    newtty.c_lflag &= ~ECHO;    newtty.c_cc[VMIN] = 1;    newtty.c_cc[VTIME] = 0;    if (tcsetattr(0, TCSAFLUSH, &newtty) == -1) {	printf("cannot put tty into raw mode\n");	error_end(1);    }    tcgetattr(0, &Rawtty);}int main(int argc, char **argv){    /* For select(2). */    struct timeval tv;    fd_set in;    /* For parsing arguments. */    char *cp;    /* The key read in. */    char c;    struct sigaction sact;    setlocale(LC_ALL, "");    get_options();        /* set to PCPU sorting */    register_sort_function( -1, (cmp_t)pcpu_sort);        /*     * Parse arguments.     */    argv++;    while (*argv) {	cp = *argv++;	while (*cp) {	    switch (*cp) {	      case 'd':	        if (cp[1]) {		    if (sscanf(++cp, "%f", &Sleeptime) != 1) {			fprintf(stderr, PROGNAME ": Bad delay time `%s'\n", cp);			exit(1);		    }		    goto breakargv;		} else if (*argv) { /* last char in an argv, use next as arg */		    if (sscanf(cp = *argv++, "%f", &Sleeptime) != 1) {			fprintf(stderr, PROGNAME ": Bad delay time `%s'\n", cp);			exit(1);		    }		    goto breakargv;		} else {		    fprintf(stderr, "-d requires an argument\n");		    exit(1);		}		break;	      case 'n':		if (cp[1]) {	   	    if (sscanf(++cp, "%d", &Loops) != 1) {			fprintf(stderr, PROGNAME ": Bad value `%s'\n", cp);			exit(1);		    }		    goto breakargv;		} else if (*argv) { /* last char in an argv, use next as arg */		    if (sscanf(cp = *argv++, "%d", &Loops) != 1) {			fprintf(stderr, PROGNAME ": Bad value `%s'\n", cp);			 exit(1);	 	     }		     goto breakargv;		}		break;						      case 'q':		if (!getuid())		    /* set priority to -10 in order to stay above kswapd */		    if (setpriority(PRIO_PROCESS, getpid(), -10)) {			/* We check this just for paranoia.  It's not			   fatal, and shouldn't happen. */			perror(PROGNAME ": setpriority() failed");		    }		Sleeptime = 0;		break;	      case 'p':		if (monpids_index >= monpids_max) {		    fprintf(stderr, PROGNAME ": More than %u process ids specified\n",			    monpids_max);		    exit(1);		}		if (cp[1]) {		    if (sscanf(++cp, "%d", &monpids[monpids_index]) != 1 ||			monpids[monpids_index] < 0 || monpids[monpids_index] > 65535) {			fprintf(stderr, PROGNAME ": Bad process id `%s'\n", cp);			exit(1);		    }		} else if (*argv) { /* last char in an argv, use next as arg */		    if (sscanf(cp = *argv++, "%d", &monpids[monpids_index]) != 1 ||			monpids[monpids_index] < 0 || monpids[monpids_index] > 65535) {			fprintf(stderr, PROGNAME ": Bad process id `%s'\n", cp);			exit(1);		    }		} else {		    fprintf(stderr, "-p requires an argument\n");		    exit(1);		}		if (!monpids[monpids_index])		    monpids[monpids_index] = getpid();		/* default to no sorting when monitoring process ids */		if (!monpids_index++) {		    sort_type = S_NONE;		    reset_sort_options();		}		cp = "_";		break;	      case 'b':		Batch = 1;	        break;	      case 'c':	        show_cmd = !show_cmd;		break;	      case 'S':		Cumulative = 1;		break;	      case 'i':		Noidle = 1;		break;	      case 's':		  Secure = 1;		  break;	      case 'C':		  CPU_states = 1;		  break;	      case '-':		break;		/* Just ignore it */ 	      case 'v': 	      case 'V': 		fprintf(stdout, "top (%s)\n", procps_version); 		exit(0);	      case 'h': 		fprintf(stdout, "usage: " PROGNAME " -hvbcisqS -d delay -p pid -n iterations\n");		exit(0);	      default:		fprintf(stderr, PROGNAME ": Unknown argument `%c'\n", *cp); 		fprintf(stdout, "usage: " PROGNAME " -hvbcisqS -d delay -p pid -n iterations\n");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -