wanted: 'load' %cpu usage display -- DISPLAY

William L. Sebok wls at astrovax.UUCP
Fri Mar 7 12:17:40 AEST 1986


In article <13800005 at uicsl> guzolek at uicsl.UUCP writes:
>A while back (around Oct, Nov of 1984) A program called "load"
>showed up on net.sources.  This program produced a histogram display
>on the screen of the current load on the system.
>Each line of the display was a persons login name, followed by the
>%cpu usage followed by a histogram bar of that usage.
>Each process a user started was shown separately so a user with several
>processes running would show up multiple times.  Small usage users
>processes were not shown but their sum total was displayed as
>RESIDUAL followed by a histogram.  The display was sorted as to show
>the heaviest users first and on down.
>The program was much faster than 'ps' and was useful to get a quick
>simple picture of who was loading the system.  The program Was written
>in C I believe and we used it under 4.2bsd.

I don't know about "load" but I did post a program program by that description
at about that time.  Since it was fairly short here it is again.
Bill Sebok			Princeton University, Astrophysics
{allegra,akgua,cbosgd,decvax,ihnp4,noao,philabs,princeton,vax135}!astrovax!wls
-----Cut Here----
: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
	all=TRUE
fi
/bin/echo 'Extracting Makefile'
sed 's/^X//' <<'//go.sysin dd *' >Makefile
CARGS=  -pg # -O -# -DCANREAD
LARGS= -pg # -s # -pg

display:	display.o
	cc -o display  $(LARGS) display.o -lcurses -ltermcap -lnm

display.o:	display.c
	cc -O -c $(CARGS) display.c

clean:
	rm -f display display.o
//go.sysin dd *
made=TRUE
if [ $all = TRUE ]; then
	/bin/echo '	Changing owner to "root"'
	/etc/chown root Makefile
else
	/bin/echo '	Original owner was "root"'
fi
if [ $made = TRUE ]; then
	/bin/chmod 644 Makefile
	/bin/echo -n '	'; /bin/ls -ld Makefile
fi
/bin/echo 'Extracting display.1'
sed 's/^X//' <<'//go.sysin dd *' >display.1
X.TH DISPLAY 1 local 1/26/83
X.SH NAME
display \- display bar graph of system use
X.SH SYNOPSIS
X.B display
[
-\fBT\fRterm ] [ n ]
X.SH DESCRIPTION
X.PP
X.I Display
displays a bar graph, showing  the process number,
the owner, and the percent cpu usage of all currently running processes
with cpu usage of at least 0.001%. All remaining cpu time is lumped into
an
X.I RESIDUAL
entry.
X.PP
The optional argument
X.I n
causes
X.I display
to update the bar graph every
X.I n
seconds.
Exit is by interrupt.
X.PP
The first display shows the cpu usage averaged over the past with a filter
of time constant 20 seconds.
Subsequent displays show the cpu usage over the last interval.
X.PP
The optional -\fBT\fRterm flag causes control codes to be generated for terminal
X.I term
rather than for the default terminal specified in the TERM environment variable.
X.SH FILES
X/etc/passwd /dev/kmem /vmunix
X.SH SEE ALSO
ps(1) w(1) finger(1)
X.SH AUTHOR
William L. Sebok
X.SH BUGS
X.PP
If a process dies between intervals its cpu usage will incorrectly show
up in RESIDUAL.
X.PP
Time in interrupt handlers also shows up in RESIDUAL.
X.PP
Cpu times for an interval are a funny exponentially weighed average
over the interval.
//go.sysin dd *
made=TRUE
if [ $all = TRUE ]; then
	/bin/echo '	Changing owner to "root"'
	/etc/chown root display.1
else
	/bin/echo '	Original owner was "root"'
fi
if [ $made = TRUE ]; then
	/bin/chmod 644 display.1
	/bin/echo -n '	'; /bin/ls -ld display.1
fi
/bin/echo 'Extracting display.c'
sed 's/^X//' <<'//go.sysin dd *' >display.c
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * **
 ** * * * * * display: show percent cpu use * * * * * * * * * * * * * * * *
 * * * * * * * * * * * * * * * * * * * * * * * * Nov 11,1982 W.Sebok * * **
 ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <sys/param.h>

#include <signal.h>
#ifdef SIGIO
#define BSD4_2
#endif

#ifdef BSD4_2
#include <sys/time.h>
#include <sys/quota.h>
#else BSD4_2
#include <sys/vtimes.h>
#endif BSD4_2
#include <sys/proc.h>
#include <curses.h>
#include <nlist.h>

struct	nlist nls[] = {
#define	X_PROC		0
	{ "_proc" },
#define	X_NPROC		1
	{ "_nproc" },
	{ 0 },
};

extern char **environ;
char term[] = "TERM=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ;
char *env[2] = { term , 0 } ;

#define NBAR 55
#define MXSHOWN 20
X/* exp(-1/20) */
#define	CCPU	0.95122942450071400909e0

struct usrs {
	double us_pctcpu ;
	double us_opctcpu ;
	short us_uid ;
	short us_pid ;
	char  us_valid ;
}

main(argc,argv)
int argc;
char *argv[];
{
	int kmem ;
	register int i, j ;
	register struct proc *pp ;
	register char *p, *op ;
	int nproc, nxs, addr ;
	double ccpu, acpu, bcpu, t ;
	int tim, ntab, ontab ;
	struct proc  *proc ;
	char *calloc(), *malloc(), *fgets(), lin[120] ;
	int nusers ;
	void done() ;
	int cmp_us();
	FILE *fil ;

	struct usrs idle, *users, **tab ;

	char **names ;

	register struct usrs *us ;

	static char VMUNIX[] = "/vmunix" ;
	static char KMEM[]   = "/dev/kmem" ;
	static char USAGE[] = "Usage: display [ -Tterm ] [ time ]\n" ;
	static char NPERR[] = "/vmunix: _nproc not in namelist\n" ;
	static char PERR[]  = "/vmunix: _proc not in namelist\n" ;

	idle.us_uid = -1 ;
	idle.us_pid = -1 ;

	/*
	 * set alternate terminal option
	 */

	if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'T') {
		environ = env ;
		(void)strcat(&term[5],&argv[1][2]) ;
		argv++ ; argc-- ;
	}

	if(argc > 2) {
		(void)write(2,USAGE, sizeof(USAGE)) ;
		exit(1);
	}

	tim = (argc==2) ? atoi(*(++argv)) : 0 ;
	if (tim!=0) {
		(void)signal(2,done) ;
		initscr() ;
		for (i=0 , ccpu=1e0 ; i<tim ; i++) ccpu *= CCPU ;
		acpu = 1e0/(1e0-ccpu) ;
		bcpu = ccpu/(1e0-ccpu) ;
		ontab = 0 ;
	}

	if((kmem = open(KMEM,0)) < 0) {
		perror(KMEM);
		exit(1);
	}


	fil = fopen("/etc/passwd","r") ;
	if (fil==NULL) {
		fprintf(stderr,"Unable to Open /etc/passwd.\n") ;
		exit(1) ;
	}


X/* Scan for number of users */

	nusers = 0 ;

	while (fgets(lin,120,fil) != NULL) {
		p = lin ;
		while (*p != ':') p++ ;
		*p++ = '\0' ;
		while (*p != ':') p++ ;
		op = ++p ;
		while (*p != ':') p++ ;
		*p = '\0' ;
		i = atoi(op) ;
		nusers = (i>nusers) ? i : nusers ;	/* max */
	}

	rewind(fil) ;

	names = (char**)calloc(nusers+2,sizeof(char *));
	names[0] = "RESIDUAL" ;

X/* Get User Names */

	while (fgets(lin,120,fil) != NULL) {
		p = lin ;
		while (*p != ':') p++ ;
		*p++ = '\0' ;
		j = p - lin ;
		while (*p != ':') p++ ;
		op = ++p ;
		while (*p != ':') p++ ;
		*p = '\0' ;
		i = atoi(op) ;
		if (names[i+1])
			continue;
		names[i+1] = (char*)calloc(j,sizeof(char)) ;
		strcpy(names[i+1], lin) ;
	}
	fclose(fil) ;

	/*
	 * Locate proc table
	 */

	nlist(VMUNIX, nls) ;

	if ((addr = nls[X_NPROC].n_value) == 0) {
		(void)write(2,NPERR,sizeof NPERR) ;
		exit(1) ;
	}
#ifdef CANREAD
	nproc = *( (int*) addr) ;
#else
	(void)lseek(kmem,(long)addr, 0);
	(void)read(kmem, (char*)&nproc, sizeof nproc);
#endif

	users = (struct usrs *) calloc((int)nproc, sizeof(struct usrs)) ;
	tab = (struct usrs **) calloc((int)nproc, sizeof(struct usrs *)) ;

#ifndef CANREAD
	proc = (struct proc *) calloc((int)nproc, sizeof(struct proc)) ;
#endif

	if ((addr = nls[X_PROC].n_value) == 0) {
		(void)write(2,PERR,sizeof PERR) ;
		exit(1) ;
	}
#ifdef CANREAD
	proc = *( (struct proc **) addr) ;
#else
	(void)lseek(kmem,(long)addr,0) ;
	(void)read(kmem, (char*)&addr, sizeof addr) ;
#endif

	for (i=0 ; i<nproc ; i++) {
		users[i].us_pid = -1 ;
	}

	for (;;) {

		/* Read Proc Table */

#ifndef CANREAD
		(void)lseek(kmem,(long)addr,0) ;
		(void)read(kmem, (char*)proc, nproc * (sizeof *proc)) ;
#endif

		ntab = 0 ; idle.us_pctcpu = 1e0 ;

		/* Scan for processes */
		for (pp=proc, us=users, i=0 ; i<nproc; pp++, i++, us++) {
			if ((pp->p_flag)&SLOAD) {
				tab[ntab++] = us ;
				if (us->us_pid == pp->p_pid) {
					if (us->us_valid) {
						t =   acpu*(pp->p_pctcpu)
					 	    - bcpu*(us->us_opctcpu) ;
						us->us_pctcpu = (t<0) ? 0 : t;
						us->us_opctcpu = pp->p_pctcpu;
					} else {
						us->us_valid++;
						us->us_pctcpu = us->us_opctcpu
						  = pp->p_pctcpu ;
					}
				} else {
					us->us_valid=0;
					us->us_uid = pp->p_uid ;
					us->us_pid = pp->p_pid ;
					us->us_pctcpu = pp->p_pctcpu ;
				}
				if ( (t=us->us_pctcpu) > 0)
					idle.us_pctcpu -= t ;
				if (t<1e-3)
					ntab-- ;
			}
		}

		if (idle.us_pctcpu>1e-3) tab[ntab++] = &idle ;

		/* Sort Index of Users */
		qsort(tab, ntab, sizeof(struct usrs *), cmp_us);

		if  (ntab>MXSHOWN)  ntab = MXSHOWN  ;

		/* display top MXSHOWN processes */
		for (i=0 ; i<ntab ; i++) {
			us = tab[i] ;
			nxs = NBAR*(us->us_pctcpu) ;
			nxs = (nxs>NBAR) ? NBAR : nxs ;
			for (j=0, p=lin ; j<nxs ; j++ ) *p++ = '#' ;
			for (; j<NBAR ; j++) *p++ = ' ' ;
			*p = '\0' ;

			if (tim>0) {
				if (us->us_pid>=0) {
					printw(
						"%8s %5d %7.3f %s\n",
						names[us->us_uid+1],
						us->us_pid,
						100*us->us_pctcpu,
						lin) ;
				} else {
					printw(
						"%8s   *** %7.3f %s\n",
						names[us->us_uid+1],
						100*us->us_pctcpu,
						lin) ;
				}
			} else {
				if (us->us_pid>=0) {
					printf("%8s %5d %7.3f %s\n",
						names[us->us_uid+1],
						us->us_pid,
						100*us->us_pctcpu,
						lin) ;
				} else {
					printf(
						"%8s   *** %7.3f %s\n",
						names[us->us_uid+1],
						100*us->us_pctcpu,
						lin) ;
				}
			}
		}

		if (tim<=0) exit(0) ;

		for (i=ntab ; i<=ontab ; i++) {	/* clear out dead lines */
			clrtoeol() ;
			printw("\n") ;
		}

		refresh() ;
		ontab = ntab ;
		sleep(tim) ;
		move(0,0) ;
	}
}

void done() {
	endwin() ;
	exit(0) ;
}

cmp_us(us1,us2)
	register struct usrs **us1, **us2;
{
	double f;

	f = (*us2)->us_pctcpu - (*us1)->us_pctcpu;

	if (f>0e0) return(1);
	if (f<0e0) return(-1);

	return(0);
}
//go.sysin dd *
made=TRUE
if [ $all = TRUE ]; then
	/bin/echo '	Changing owner to "root"'
	/etc/chown root display.c
else
	/bin/echo '	Original owner was "root"'
fi
if [ $made = TRUE ]; then
	/bin/chmod 644 display.c
	/bin/echo -n '	'; /bin/ls -ld display.c
fi
exit 0
-----Cut Here---
-- 
Bill Sebok			Princeton University, Astrophysics
{allegra,akgua,cbosgd,decvax,ihnp4,noao,philabs,princeton,vax135}!astrovax!wls



More information about the Comp.sources.unix mailing list