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

📄 m_irixsgi.c

📁 查看系统硬件和内存资源使用情况;以及各个进程的使用情况
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * top - a top users display for Unix * * SYNOPSIS:  Any SGI machine running IRIX 6.2 and up * * DESCRIPTION: * This is the machine-dependent module for IRIX as supplied by * engineers at SGI. * * CFLAGS: -DHAVE_GETOPT -D_OLD_TERMIOS -DORDER * * AUTHOR: Sandeep Cariapa <cariapa@sgi.com> * AUTHOR: Larry McVoy <lm@sgi.com> * Sandeep did all the hard work; I ported to 6.2 and fixed up some formats. * AUTHOR: John Schimmel <jes@sgi.com> * He did the all irix merge. * AUTHOR: Ariel Faigon <ariel@sgi.com> *	Ported to Ficus/Kudzu (IRIX 6.4+). *	Got rid of all nlist and different (elf64, elf32, COFF) kernel *	dependencies *	Various small fixes and enhancements: multiple CPUs, nicer formats. *	Added -DORDER process display ordering *	cleaned most -fullwarn'ings. *	Need -D_OLD_TERMIOS when compiling on IRIX 6.4 to work on 6.2 systems *	Support much bigger values in memory sizes (over Peta-byte) */#define _KMEMUSER#include <sys/types.h>#include <sys/time.h>#include <sys/stat.h>#include <sys/swap.h>#include <sys/proc.h>#include <sys/procfs.h>#include <sys/sysinfo.h>#include <sys/sysmp.h>#include <sys/utsname.h>#include <sys/schedctl.h>	/* for < 6.4 NDPHIMAX et al. */#include <paths.h>#include <assert.h>#include <values.h>#include <dirent.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <errno.h>#include <fcntl.h>#include <dlfcn.h>#include "top.h"#include "machine.h"#define KMEM	"/dev/kmem"typedef double load_avg;#define loaddouble(la) (la)#define intload(i) ((double)(i))/* * Structure for keeping track of CPU times from last time around * the program.  We keep these things in a hash table, which is * recreated at every cycle. */struct oldproc {	pid_t	oldpid;	double	oldtime;	double	oldpct;};static int oldprocs;                    /* size of table */static struct oldproc *oldbase;#define HASH(x) ((x << 1) % oldprocs)#define pagetok(pages) ((((uint64_t) pages) * pagesize) >> 10)/* * Ugly hack, save space and complexity of allocating and maintaining * parallel arrays to the prpsinfo array: use spare space (pr_fill area) * in prpsinfo structures to store %CPU calculated values */#define D_align(addr)		(((unsigned long)(addr) & ~0x0fU))#define percent_cpu(pp)		(* (double *) D_align(&((pp)->pr_fill[0])))#define weighted_cpu(pp)	(* (double *) D_align(&((pp)->pr_fill[4])))/* Username field to fill in starts at: */#define UNAME_START 16/* *  These definitions control the format of the per-process area */static char header[] ="    PID    PGRP X         PRI   SIZE   RES STATE    TIME %WCPU  %CPU COMMAND";/* 012345678901234567890123456789012345678901234567890123456789012345678901234567          10        20        30        40        50        60        70 *//*       PID PGRP USER  PRI   SIZE  RES   STATE  TIME  %WCPU %CPU  CMD */#define Proc_format \	"%7d %7d %-8.8s %4.4s %6.6s %5.5s %-6.6s %6.6s %5.2f %5.2f %-.10s"/* * these are for detailing the cpu states * Data is taken from the sysinfo structure (see <sys/sysinfo.h>) * We rely on the following values: * *	#define CPU_IDLE        0 *	#define CPU_USER        1 *	#define CPU_KERNEL      2 *	#define CPU_WAIT        3 *	#define CPU_SXBRK       4 *	#define CPU_INTR        5 */#ifndef CPU_STATES	/* defined only in 6.4 and up */# define CPU_STATES 6#endifint	cpu_states[CPU_STATES];char	*cpustatenames[] = {	"idle", "usr", "ker", "wait", "xbrk", "intr",	NULL};/* these are for detailing the memory statistics */#define MEMSTATS 10int	memory_stats[MEMSTATS];char	*memorynames[] = {	"K max, ", "K avail, ", "K free, ", "K swap, ", "K free swap", NULL};char	uname_str[40];double	load[3];static  char fmt[MAX_COLS + 2];int	numcpus;/* useful externals */extern int	errno;extern char	*sys_errlist[];extern char	*myname;extern char	*format_k();extern char	*format_time();extern long	percentages();static int kmem;static unsigned long avenrun_offset;static float	irix_ver;		/* for easy numeric comparison */static struct prpsinfo	*pbase;static struct prpsinfo	**pref;static struct oldproc	*oldbase;static int		oldprocs;	/* size of table */static DIR	*procdir;static int	ptable_size;	/* allocated process table size */static int	nproc;		/* estimated process table size */static int	pagesize;/* get_process_info passes back a handle.  This is what it looks like: */struct handle {	struct prpsinfo **next_proc;	/* points to next valid proc pointer */	int		remaining;	/* number of pointers remaining */};static struct handle	handle;void getptable(struct prpsinfo *baseptr);void size(int fd, struct prpsinfo *ps);extern char *ordernames[];/* * Process states letters are mapped into numbers * 6.5 seems to have changed the semantics of prpsinfo.pr_state * so we rely, (like ps does) on the char value pr_sname. * The order we use here is what may be most interesting * to top users:  Most interesting state on top, least on bottom. * 'S' (sleeping) is the most common case so I put it _after_ * zombie, even though it is more "active" than zombie. * * State letters and their meanings: * *	R   Process is running (may not have a processor yet) *	I   Process is in intermediate state of creation *	X   Process is waiting for memory *	T   Process is stopped *	Z   Process is terminated and parent not waiting (zombie) *	S   Process is sleeping, waiting for a resource *//* abbreviated process states */static char *state_abbrev[] ={ "", "sleep", "zomb", "stop", "swap", "start", "ready", "run", NULL };/* Same but a little "wordier", used in CPU activity summary */int     process_states[8];	/* per state counters */char	*procstatenames[] = {	/* ready to run is considered running here */	"",		" sleeping, ",	" zombie, ",	" stopped, ",	" swapped, ",	" starting, ",	" ready, ",	" running, ",	NULL};#define S_RUNNING	7#define S_READY		6#define S_STARTING	5#define S_SWAPPED	4#define S_STOPPED	3#define S_ZOMBIE	2#define S_SLEEPING	1#define IS_ACTIVE(pp) \	(first_screen ? proc_state(pp) >= S_STARTING : percent_cpu(pp) > 0.0)/* * proc_state *	map the pr_sname value to an integer. *	used as an index into state_abbrev[] *	as well as an "order" key */static int proc_state(struct prpsinfo *pp){    char psname = pp->pr_sname;    switch (psname) {	case 'R': return		 (pp->pr_sonproc >= 0 && pp->pr_sonproc < numcpus) ?			S_RUNNING /* on a processor */ : S_READY;	case 'I': return S_STARTING;	case 'X': return S_SWAPPED;	case 'T': return S_STOPPED;	case 'Z': return S_ZOMBIE;	case 'S': return S_SLEEPING;	default : return 0;    }}/* * To avoid nlist'ing the kernel (with all the different kernel type * complexities), we estimate the size of the needed working process * table by scanning  /proc/pinfo and taking the number of entries * multiplied by some reasonable factor. * Assume current dir is _PATH_PROCFSPI */static int active_proc_count(){	DIR	*dirp;	int	pcnt;	if ((dirp = opendir(".")) == NULL) {		(void) fprintf(stderr, "%s: Unable to open %s\n",					myname, _PATH_PROCFSPI);		exit(1);	}	for (pcnt = 0; readdir(dirp) != NULL; pcnt++)		;	closedir(dirp);	return pcnt;}/* * allocate space for: *	proc structure array *	array of pointers to the above (used for sorting) *	array for storing per-process old CPU usage */voidallocate_proc_tables(){	int	n_active = active_proc_count();	if (pbase != NULL)  /* && n_active < ptable_size */		return;	/* Need to realloc if we exceed, but factor should be enough */	nproc = n_active * 5;	oldprocs = 2 * nproc;	pbase = (struct prpsinfo *)		malloc(nproc * sizeof(struct prpsinfo));	pref = (struct prpsinfo **)		malloc(nproc * sizeof(struct prpsinfo *));	oldbase = (struct oldproc *)		malloc (oldprocs * sizeof(struct oldproc));	ptable_size = nproc;	if (pbase == NULL || pref == NULL || oldbase == NULL) {		(void) fprintf(stderr, "%s: malloc: out of memory\n", myname);		exit (1);	}}intmachine_init(struct statics *statics){	struct oldproc	*op, *endbase;	int		pcnt = 0;	struct utsname	utsname;	char		tmpbuf[20];	uname(&utsname);	irix_ver = (float) atof((const char *)utsname.release);	strncpy(tmpbuf, utsname.release, 9);	tmpbuf[9] = '\0';	sprintf(uname_str, "%s %-.14s %s %s",		utsname.sysname, utsname.nodename,		tmpbuf, utsname.machine);	pagesize = getpagesize();	if ((kmem = open(KMEM, O_RDONLY)) == -1) {		perror(KMEM);		return -1;	}	if (chdir(_PATH_PROCFSPI)) {		/* handy for later on when we're reading it */		(void) fprintf(stderr, "%s: Unable to chdir to %s\n",					myname, _PATH_PROCFSPI);		return -1;	}	if ((procdir = opendir(".")) == NULL) {		(void) fprintf(stderr, "%s: Unable to open %s\n",					myname, _PATH_PROCFSPI);		return -1;	}	if ((avenrun_offset = sysmp(MP_KERNADDR, MPKA_AVENRUN)) == -1) {		perror("sysmp(MP_KERNADDR, MPKA_AVENRUN)");		return -1;	}	allocate_proc_tables();	oldprocs = 2 * nproc;	endbase = oldbase + oldprocs;	for (op = oldbase; op < endbase; op++) {		op->oldpid = -1;	}	statics->cpustate_names = cpustatenames;	statics->memory_names = memorynames;	statics->order_names = ordernames;	statics->procstate_names = procstatenames;	return (0);}char   *format_header(uname_field)	register char *uname_field;{	register char *ptr;	ptr = header + UNAME_START;	while (*uname_field != '\0') {		*ptr++ = *uname_field++;	}	return (header);}voidget_system_info(si)	struct system_info *si;{	int		i;	int		avenrun[3];	struct rminfo	realmem;	struct sysinfo	sysinfo;	static time_t	cp_old [CPU_STATES];	static time_t	cp_diff[CPU_STATES];	/* for cpu state percentages */	off_t		fswap;		/* current free swap in blocks */	off_t		tswap;		/* total swap in blocks */	(void) getkval(avenrun_offset, (int *) avenrun, sizeof(avenrun), "avenrun");	for (i = 0; i < 3; i++) {		si->load_avg[i] = loaddouble(avenrun[i]);		si->load_avg[i] /= 1024.0;	}	if ((numcpus = sysmp(MP_NPROCS)) == -1) {		perror("sysmp(MP_NPROCS)");		return;	}	if (sysmp(MP_SAGET, MPSA_RMINFO, &realmem, sizeof(realmem)) == -1) {		perror("sysmp(MP_SAGET,MPSA_RMINFO, ...)");		return;	}	swapctl(SC_GETFREESWAP, &fswap);	swapctl(SC_GETSWAPTOT, &tswap);	memory_stats[0] = pagetok(realmem.physmem);	memory_stats[1] = pagetok(realmem.availrmem);	memory_stats[2] = pagetok(realmem.freemem);	memory_stats[3] = tswap / 2;	memory_stats[4] = fswap / 2;	if (sysmp(MP_SAGET,MPSA_SINFO, &sysinfo,sizeof(struct sysinfo)) == -1) {		perror("sysmp(MP_SAGET,MPSA_SINFO)");		return;	}	(void) percentages(CPU_STATES, cpu_states, sysinfo.cpu, cp_old, cp_diff);	si->cpustates = cpu_states;	si->memory = memory_stats;	si->last_pid = -1;	return;}caddr_tget_process_info(si, sel, compare)	struct system_info *si;	struct process_select *sel;	int     (*compare) ();{	int		i, total_procs, active_procs;	struct prpsinfo	**prefp;	struct prpsinfo	*pp;	int		show_uid;	static char	first_screen = 1;	/* read all the proc structures */	getptable(pbase);	/* get a pointer to the states summary array */	si->procstates = process_states;	/* set up flags which define what we are going to select */	show_uid = sel->uid != -1;	/* count up process states and get pointers to interesting procs */	total_procs = 0;	active_procs = 0;	(void) memset(process_states, 0, sizeof(process_states));	prefp = pref;	for (pp = pbase, i = 0; i < nproc; pp++, i++) {		/*		 * Place pointers to each valid proc structure in pref[].		 * Process slots that are actually in use have a non-zero		 * status field.  Processes with SSYS set are system		 * processes---these get ignored unless show_system is set.		 * Ariel: IRIX 6.4 had to redefine "system processes"		 * They do not exist outside the kernel in new kernels.		 * Now defining as uid==0 and ppid==1 (init children)		 */		if (pp->pr_state &&			(sel->system || !(pp->pr_uid==0 && pp->pr_ppid==1))) {			total_procs++;			process_states[proc_state(pp)]++;			/*			 * zombies are actually interesting (to avoid)			 * although they are not active, so I leave them			 * displayed.			 */			if (/* (! pp->pr_zomb) && */			    (sel->idle || IS_ACTIVE(pp)) &&			    (! show_uid || pp->pr_uid == (uid_t) sel->uid)) {				*prefp++ = pp;				active_procs++;			}		}	}	first_screen = 0;	/* if requested, sort the "interesting" processes */	if (compare != NULL)		qsort((char *) pref, active_procs, sizeof(struct prpsinfo *), compare);	/* remember active and total counts */	si->p_total = total_procs;	si->p_active = active_procs;	/* pass back a handle */	handle.next_proc = pref;	handle.remaining = active_procs;	return ((caddr_t) &handle);}/* * Added cpu_id to running processes, add 'ready' (to run) state */static char * format_state(struct prpsinfo *pp){	static char	state_str[16];	int		state = proc_state(pp);	if (state == S_RUNNING) {		/*		 * Alert: 6.2 (MP only?) binary incompatibility		 * pp->pr_sonproc apparently (?) has a different		 * offset on 6.2 machines... I've seen cases where		 * a 6.4 compiled top running on 6.2 printed		 * a garbage CPU-id. To be safe, I print the CPU-id		 * only if it falls within range [0..numcpus-1]		 */		sprintf(state_str, "run/%d", pp->pr_sonproc);		return state_str;	}	/* default */	return state_abbrev[state];}static char *format_prio(pp)	struct prpsinfo *pp;{    static char	prio_str[10];    if (irix_ver < 6.4) {	/*	 * Note: this is _compiled_ on 6.x where x >= 4 but I would like	 * it to run on 6.2 6.3 as well (backward binary compatibility).	 * Scheduling is completely different between these IRIX versions	 * and some scheduling classes may even have different names.	 *	 * The solution: have more than one style of 'priority' depending	 * on the OS version.	 *	 * See npri(1) + nice(2) + realtime(5) for scheduling classes,	 * and priority values.	 */

⌨️ 快捷键说明

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