display --- bar graph of top cpu using processes
William L. Sebok
wls at astrovax.UUCP
Fri Aug 10 07:54:51 AEST 1984
This is a program for 4.X BSD Unix that prints and continously updates a
bar graph of the top cpu using processes. It uses curses and termcap.
Enjoy,
Bill Sebok 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= -O # -DCANREAD
LARGS= -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 [ $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 [ $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
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() ;
FILE *fil ;
struct usrs {
double us_pctcpu ;
double us_opctcpu ;
short us_uid ;
short us_pid ;
char us_valid ;
} 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) ;
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 ;
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 */
for (i=1 ; i<ntab ; i++) {
for (j=0; j<i ; j++) {
if (tab[j]->us_pctcpu < tab[i]->us_pctcpu) {
us = tab[i] ;
tab[i] = tab[j] ;
tab[j] = us ;
}
}
}
if (ntab>MXSHOWN) ntab = MXSHOWN ;
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) ;
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
/bin/chmod 644 display.c
/bin/echo -n ' '; /bin/ls -ld display.c
fi
exit
--------If this line is not here something is missing----------------
--
Bill Sebok Princeton University, Astrophysics
{allegra,akgua,burl,cbosgd,decvax,ihnp4,noao,princeton,vax135}!astrovax!wls
More information about the Comp.sources.unix
mailing list