home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sources.unix
- From: vesper@kong.gsfc.nasa.gov (Greg Vesper Code 520.9)
- Subject: v26i009: cputt - monitor top ten (by cpu time) processes on SunOS
- Sender: unix-sources-moderator@pa.dec.com
- Approved: vixie@pa.dec.com
-
- Submitted-By: vesper@kong.gsfc.nasa.gov (Greg Vesper Code 520.9)
- Posting-Number: Volume 26, Issue 9
- Archive-Name: cputt
-
- This utility is called 'cputt'. It provides dynamic updates of the top
- ten cpu using processes on your system. It has been trimmed down to
- run as efficiently as possible and should compile and run on any system
- running SUNOS 4.1.1. This program is similar in functionality to 'top',
- also available in the public domain, but cputt is more efficient and
- is tailored for 4.1.1. Please give it a try and let me know what you
- think.
- Greg Vesper Code 520.9
- Goddard Space Flight Center
- vesper@kong.gsfc.nasa.gov
- Greenbelt, Maryland
-
- [ The output of this tool looks like this:
-
- sunburst% ./cputt 3 3
-
- PID USER CPU MEM COMMANDS - 1 42
- 10152 vixie 3.97 5.79 ./cputt 3 3
-
- PID USER CPU MEM COMMANDS - 2 42
- 10152 vixie 20.00 6.14 ./cputt 3 3
- 3038 root 0.53 2.48 in.rwhod
-
- PID USER CPU MEM COMMANDS - 2 42
- 10152 vixie 19.73 6.26 ./cputt 3 3
- 10008 root 0.26 2.83 in.rlogind
-
- I edited the Makefile for cosmetic things. This builds and runs
- on a Sun SPARC machine. --vix ]
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: README Makefile cputt.h getcmd.c globals.c hash.c init.c
- # main.c routines.c
- # Wrapped by vixie@cognition.pa.dec.com on Sun Apr 19 07:06:29 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(3576 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- X Cputt - CPU Top Ten monitor for SUNOS 4.1.1
- X ===========================================
- X
- DISCLAIMER:
- X
- X This software has no warranty whatsoever, explicit or implicit.
- X The author and his employer shall not be held responsible for any
- X damage, direct or indirect, resulting from the use of this
- X software. That being said, feel free to use it, its a useful
- X little utility.
- X
- PURPOSE:
- X
- X Cputt is a cpu monitoring utility which gives you a continuous
- X update of the top ten cpu-using processes on your system.
- X
- IMPLEMENTATION:
- X
- X Cputt takes two snapshots of the kernel process table, sleeping
- X for a user supplied number of seconds in between the two
- X snapshots. It calculates cpu usage for each process over that
- X interval and prints out the results. Execution continues for a
- X user supplied number of iterations.
- X
- USAGE:
- X
- X Cputt should be invoked with two arguments as follows:
- X
- X cputt <length of interval> <number of iterations>
- X
- X Cputt prints a sorted list of cpu intensive processes as follows:
- X
- X PID USER CPU MEM COMMANDS <active processes> <ptable size>
- X
- INSTALLATION:
- X
- X Cputt should compile on any system running SUNOS 4.1.1. Check
- X the #define values in cputt.h before compiling. The only one
- X you need to change is MAXUSERS which should be two times the
- X number of /etc/passwd entries on your machine. Just type
- X 'make' to compile, 'make install' to install. You must be root
- X to install Cputt. The default destination is /usr/etc.
- X
- SUGGESTION:
- X
- X Cputt becomes more and more processor intensive as the length of the
- X interval between process table lookups decreases. Thus a first
- X arguement of less than 5 is probably not real useful. I usually
- X invoke it with one of the following:
- X
- X cputt 5 100 - for short term monitoring of cpu usage
- X cputt 10 1000 - for long term monitoring of cpu usage
- X
- ACKNOWLEDGEMENTS:
- X
- X The idea for Cputt came from Larry Schuler, a friend and co-worker.
- X The implementation for Cputt was largely dependent on J. Robert Ward's
- X 'sps' utility. I used Robert's source code to learn how to make the
- X appropriate system calls for interrogating the kernel process table.
- X The rest of the alogorithm and implementation are my own.
- X
- IMPROVEMENTS:
- X
- X I've used all the shortcuts I know to make Cputt as trim as possible.
- X Floating point arithmetic is kept to a bare minimum. Internal data
- X structures are allocated dynamically based on the changing status of
- X the process table. Command arguements for each process are kept in
- X core instead of being re-evaluated at each iteration. The sort table
- X contains only active processes and no extraneous information. The
- X kernel reads account for the bulk of Cputt's processing overhead and
- X I'm unaware of anyway to alleviate this cost. If anyone has any well
- X considered suggestions about how I can improve the implemenation and
- X performance of Cputt, I would like to hear them.
- X
- COPYRIGHT:
- X
- X Feel free to distribute Cputt to any interested parties. Please
- X provide a copy of this README with any distribution.
- X
- X:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- X Greg Vesper Code 520.9
- X Goddard Space Flight Center
- X vesper@kong.gsfc.nasa.gov
- X Greenbelt, Maryland
- X
- X"As He died to make men holy, let us live to make men free.
- X While God is marching on.."
- X:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- END_OF_FILE
- if test 3576 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(581 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- DESTROOT =
- DESTPATH = $(DESTROOT)/usr/local
- X
- PROG = cputt
- OBJS = globals.o init.o getcmd.o hash.o routines.o main.o
- CC = cc
- CDEBUG = -O
- CFLAGS = $(CDEBUG)
- LIBS = -lkvm
- DIRINSTALL = $(DESTPATH)/bin
- X
- all: $(PROG)
- X
- X.c.o:
- X $(CC) $(CFLAGS) -c -R $<
- X
- globals.o:
- X $(CC) $(CFLAGS) -c $<
- X
- X$(OBJS): cputt.h
- X
- X$(PROG): $(OBJS)
- X $(CC) -o $@ $(OBJS) $(LIBS)
- X
- install: $(PROG)
- X strip $(PROG)
- X cp $(PROG) $(DIRINSTALL)/$(PROG)
- X /etc/chown root $(DIRINSTALL)/$(PROG)
- X chgrp kmem $(DIRINSTALL)/$(PROG)
- X chmod 2755 $(DIRINSTALL)/$(PROG)
- X
- clean:
- X rm -f $(OBJS) $(PROG)
- END_OF_FILE
- if test 581 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'cputt.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cputt.h'\"
- else
- echo shar: Extracting \"'cputt.h'\" \(2312 characters\)
- sed "s/^X//" >'cputt.h' <<'END_OF_FILE'
- X# include <sys/param.h>
- X# include <sys/user.h>
- X# include <sys/proc.h>
- X
- X# define MAXUSERS 300 /* set this to (length of /etc/passwd * 2) */
- X# define MAXACTIVE 50 /* max cpu-positive processes per interval */
- X# define MAXOUT 10 /* output is limitted to this many processes */
- X# define COMMAND_SIZE 51 /* set this to (width of your window - 29) */
- X# define UNAMELEN 8 /* max length for username */
- X
- X/*
- X cputt attempts to truncate unused slots at the end of the process
- X table. This usually reduces its runtime size considerably. If the
- X process table grows or shrinks by a significant amount, cputt will
- X restart itself and resize its internal data structures accordingly.
- X*/
- X
- X# define GROWTH_BUF 40 /* growth buffer, use 0 to disable truncation */
- X# define MAX_GROW 20 /* restart after proc table grows this much */
- X# define MAX_SHRINK 10 /* restart after proc table shrinks this much */
- X
- X/* info concerning a symbol table entry */
- X
- struct symbol
- X{
- X char *s_kname; /* kernel symbol name */
- X char s_indirect; /* value requires indirection */
- X caddr_t *s_info; /* corresponding info address */
- X char *s_wait; /* reason for wait, if any */
- X};
- X
- X/* single hash table entry for mapping uid's to usernames */
- X
- struct hashtab
- X{
- X short h_uid ; /* uid of user entry */
- X char h_uname[ UNAMELEN ] ; /* corresponding name */
- X};
- X
- X/* critical system info */
- X
- struct info
- X{
- X struct proc *i_proc0; /* address of process table */
- X int i_nproc; /* length of process table */
- X int i_sproc; /* size of process table */
- X int i_ecmx; /* max physical memory address*/
- X struct hashtab i_hnames[MAXUSERS]; /* hash table for usernames */
- X};
- X
- X/* for reading process upages from kernel memory */
- X
- union userstate
- X{
- X struct user u_us ;
- X char u_pg[ UPAGES ][ NBPG ] ;
- X};
- X
- X/* summary info for processes with positive cpu utilization */
- X
- struct procdata
- X{
- X struct proc *proc; /* proc structure */
- X long pctcpu; /* cpu usage */
- X int pr_cmd; /* command string index */
- X};
- END_OF_FILE
- if test 2312 -ne `wc -c <'cputt.h'`; then
- echo shar: \"'cputt.h'\" unpacked with wrong size!
- fi
- # end of 'cputt.h'
- fi
- if test -f 'getcmd.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'getcmd.c'\"
- else
- echo shar: Extracting \"'getcmd.c'\" \(1102 characters\)
- sed "s/^X//" >'getcmd.c' <<'END_OF_FILE'
- X# include "cputt.h"
- X# include <kvm.h>
- X
- X/* GETCMD - gets the command string for process p and copies it to argbuf */
- X
- getcmd ( p, argbuf )
- X
- struct proc *p;
- register char *argbuf;
- X
- X{
- X register char *cp,**ap ;
- X char **argv ;
- X register int sp=-1;
- X extern kvm_t *Flkvm ;
- X extern union userstate User ;
- X
- X if (!p->p_pid)
- X { strcpy(&argbuf[0],"Swapper"); return; }
- X if (p->p_pid == 2)
- X { strcpy(&argbuf[0],"Pager"); return; }
- X
- X if (kvm_getcmd(Flkvm,p,&User.u_us,&argv,(char ***)NULL)<0||argv==NULL)
- X {
- X argbuf[0] = '(';
- X strncpy(&argbuf[1],User.u_us.u_comm,sizeof(User.u_us.u_comm));
- X argbuf[sizeof(User.u_us.u_comm)+1] = '\0';
- X strcat(argbuf, ")" ) ;
- X }
- X else
- X {
- X ap = argv;
- X while (*ap && sp < COMMAND_SIZE-1)
- X {
- X for (cp = *ap++; *cp && sp < COMMAND_SIZE-2;)
- X argbuf[++sp] = *cp++;
- X argbuf[++sp] = ' ';
- X }
- X argbuf[sp] = '\0';
- X free(argv);
- X }
- X}
- END_OF_FILE
- if test 1102 -ne `wc -c <'getcmd.c'`; then
- echo shar: \"'getcmd.c'\" unpacked with wrong size!
- fi
- # end of 'getcmd.c'
- fi
- if test -f 'globals.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'globals.c'\"
- else
- echo shar: Extracting \"'globals.c'\" \(624 characters\)
- sed "s/^X//" >'globals.c' <<'END_OF_FILE'
- X# include "cputt.h"
- X# include "kvm.h"
- X
- struct info Info ; /* System Addresses and Info */
- X
- kvm_t *Flkvm; /* Descriptor for Kernel Memory */
- X
- union userstate User; /* Structure to Hold Upages */
- X
- struct symbol Symbollist[] = /* Symbols to Lookup */
- X{
- X { "_proc", 1, (caddr_t*)&Info.i_proc0, (char*)0 },
- X { "_nproc", 1, (caddr_t*)&Info.i_nproc, (char*)0 },
- X { "_maxmem", 1, (caddr_t*)&Info.i_ecmx, (char*)0 },
- X { (char*)0, 0, (caddr_t*)0, (char*)0 }
- X};
- END_OF_FILE
- if test 624 -ne `wc -c <'globals.c'`; then
- echo shar: \"'globals.c'\" unpacked with wrong size!
- fi
- # end of 'globals.c'
- fi
- if test -f 'hash.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'hash.c'\"
- else
- echo shar: Extracting \"'hash.c'\" \(1047 characters\)
- sed "s/^X//" >'hash.c' <<'END_OF_FILE'
- X# include "cputt.h"
- X# include <pwd.h>
- X
- X# define HASHFN1( a ) (((unsigned)(a)*91 + 17) % MAXUSERS)
- X
- X/*
- X HASHUID - Returns a pointer to a slot in the hash table that corresponds
- X to the hash table entry for `uid'. It returns a null pointer if there is
- X no such slot.
- X*/
- X
- struct hashtab *hashuid ( uid )
- X
- int uid ;
- X
- X{
- X struct hashtab *hp ;
- X extern struct info Info ;
- X
- X hp = &Info.i_hnames[ HASHFN1( uid ) ];
- X if ( hp->h_uid == uid )
- X return ( hp ) ;
- X return ( (struct hashtab*)0 ) ;
- X}
- X
- X/*
- X INITUSERS - builds the uid hash table.
- X*/
- X
- initusers ()
- X{
- X struct passwd *pw ;
- X struct hashtab *hp ;
- X struct passwd *getpwent() ;
- X
- X while ( pw = getpwent() )
- X {
- X /* Try to find a free slot in the hash table and fill it. */
- X
- X hp = &Info.i_hnames[ HASHFN1(pw->pw_uid) ];
- X if ( !hp->h_uname[0] )
- X {
- X hp->h_uid = pw->pw_uid ;
- X strncpy( hp->h_uname, pw->pw_name, UNAMELEN );
- X }
- X }
- X endpwent() ;
- X}
- END_OF_FILE
- if test 1047 -ne `wc -c <'hash.c'`; then
- echo shar: \"'hash.c'\" unpacked with wrong size!
- fi
- # end of 'hash.c'
- fi
- if test -f 'init.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'init.c'\"
- else
- echo shar: Extracting \"'init.c'\" \(2183 characters\)
- sed "s/^X//" >'init.c' <<'END_OF_FILE'
- X# include "cputt.h"
- X# include <sys/file.h>
- X# include <kvm.h>
- X# include <nlist.h>
- X# include <stdio.h>
- X
- X/*
- X INIT - Reads the kernel's symbol table for critical system
- X information and stores this information in the Symbollist array.
- X*/
- X
- init ()
- X{
- X register struct nlist *np ;
- X register struct symbol *s ;
- X register struct nlist *np0 ;
- X extern kvm_t *Flkvm ;
- X extern struct symbol Symbollist[] ;
- X extern struct info Info ;
- X char *getcore() ;
- X
- X /* find length of the list of desired symbols */
- X
- X for ( s = Symbollist ; s->s_kname ; s++ )
- X ;
- X /* allocate core for nlist array */
- X
- X np0 = (struct nlist*)getcore( (s-Symbollist+1)*sizeof( struct nlist ));
- X
- X /* initialize nlist array */
- X
- X for ( s = Symbollist, np = np0 ; s->s_kname ; s++, np++ )
- X {
- X np->n_name = s->s_kname ;
- X np[1].n_name = (char*)0 ;
- X np->n_value = 0 ;
- X }
- X
- X /* read symbols from symbol table into nlist array */
- X
- X if ( kvm_nlist( Flkvm, np0 ) == -1 )
- X {
- X fprintf( stderr, "sps - Can't read symbol file \n");
- X sysperror() ;
- X }
- X
- X /* derive system info from nlist and store in Symbollist */
- X
- X for ( s = Symbollist, np = np0 ; s->s_kname ; s++, np++ )
- X {
- X if ( !np->n_value )
- X {
- X fprintf( stderr, "sps - Can't find symbol %s in %s", np->n_name);
- X *s->s_info = (caddr_t)0 ;
- X continue ;
- X }
- X
- X /* If no indirection is required, just copy the obtained value
- X into the `Info' structure. */
- X
- X if ( !s->s_indirect )
- X {
- X *s->s_info = (caddr_t)np->n_value ;
- X continue ;
- X }
- X
- X /* Otherwise one level of indirection is required. Using the
- X obtained address, look again in the kernel for the value */
- X
- X (void)getkmem((long)np->n_value, (char*)s->s_info, sizeof(caddr_t));
- X }
- X free( (char*)np0 ) ;
- X}
- END_OF_FILE
- if test 2183 -ne `wc -c <'init.c'`; then
- echo shar: \"'init.c'\" unpacked with wrong size!
- fi
- # end of 'init.c'
- fi
- if test -f 'main.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'main.c'\"
- else
- echo shar: Extracting \"'main.c'\" \(7210 characters\)
- sed "s/^X//" >'main.c' <<'END_OF_FILE'
- X#include "cputt.h"
- X#include <kvm.h>
- X#include <fcntl.h>
- X#include <sys/stat.h>
- X#include <sys/types.h>
- X#include <sys/timeb.h>
- X#include <sys/resource.h>
- X
- X/*
- X MAIN - Computes CPU utilization for all processes from two snapshots
- X of the kernel process table taken over a user supplied interval
- X (arg1). Sorts and prints the top ten CPU using processes for that
- X interval. Execution continues for a user supplied number of
- X iterations (arg2).
- X
- X The kernel process table snapshots are stored in two arrays,
- X 'oldproc' and 'newproc'. Resource utilization information is stored
- X in two arrays, 'oldusage' and 'newusage'. The command strings for
- X each process are stored in a 2D array, 'cmds'. CPU utilization for
- X each interval is stored in the 'pdata' array along with pointers to
- X the appropriate 'proc' and 'cmds' entries.
- X*/
- X
- main (argc, argv)
- X
- int argc; char *argv[];
- X
- X{
- X extern struct info Info;
- X extern kvm_t *Flkvm;
- X extern union userstate User;
- X
- X struct proc *oldproc,*newproc,*tproc;
- X struct rusage *oldusage,*newusage,*tusage;
- X struct procdata *pdata;
- X struct hashtab *hp;
- X
- X register long time1,utime1,time2,utime2;
- X register long s_delta, p_delta;
- X register int i,j,k;
- X
- X struct timeb ot,nt;
- X struct hashtab *hashuid();
- X int trim=0,reps,cmp();
- X double percentmem();
- X char **cmds;
- X
- X if (argc != 3)
- X {
- X printf("usage: cputt <interval> <iterations>\n");
- X exit();
- X }
- X
- X setpriority(PRIO_PROCESS,0,-20);
- X
- X /* open kernel memory */
- X
- X Flkvm = kvm_open(NULL, NULL, NULL, O_RDONLY, "cputt");
- X
- X /* get critical system parameters, build uid hash table */
- X
- X init();
- X initusers();
- X
- X /* truncate unused portion of the process table */
- X
- X Info.i_sproc = Info.i_nproc * sizeof(struct proc);
- X if (GROWTH_BUF)
- X {
- X oldproc = (struct proc *) getcore(Info.i_nproc*sizeof(struct proc));
- X readstatus(oldproc);
- X for (i=0; i<Info.i_nproc; i++)
- X if (oldproc[i].p_stat && getupage(oldproc[i]))
- X j=i;
- X free(oldproc);
- X if (j+GROWTH_BUF < Info.i_nproc)
- X {
- X Info.i_nproc = j+GROWTH_BUF;
- X Info.i_sproc = Info.i_nproc * sizeof(struct proc);
- X trim = 1;
- X }
- X }
- X
- X /* allocate core for internal data structures */
- X
- X cmds = (char **) getcore(Info.i_nproc*sizeof(char *));
- X for (i=0;i<Info.i_nproc;i++)
- X cmds[i] = (char *) getcore(COMMAND_SIZE);
- X
- X pdata = (struct procdata *)
- X getcore(MAXACTIVE*sizeof(struct procdata));
- X oldusage = (struct rusage *)
- X getcore(Info.i_nproc*sizeof(struct rusage));
- X newusage = (struct rusage *)
- X getcore(Info.i_nproc*sizeof(struct rusage));
- X oldproc = (struct proc *) getcore(Info.i_nproc*sizeof(struct proc));
- X newproc = (struct proc *) getcore(Info.i_nproc*sizeof(struct proc));
- X
- X /* get initial time, process table, upage, and command strings */
- X
- X ftime(&ot);
- X readstatus(oldproc);
- X for (i=0;i<Info.i_nproc;i++)
- X if (oldproc[i].p_stat && getupage(oldproc[i]))
- X {
- X oldusage[i] = User.u_us.u_ru;
- X getcmd(oldproc[i],cmds[i]);
- X }
- X
- X /* compare process tables every argv[1] seconds for argv[2] iterations */
- X
- X for (reps = 0; reps < atoi(argv[2]); reps++)
- X {
- X sleep(atoi(argv[1])); /* sleep for agrv[1] seconds */
- X ftime(&nt); /* get new time */
- X readstatus(newproc); /* get new process table */
- X
- X /* find matching pids, compute cpu usage, store results in pdata */
- X
- X for (i=k=0; i<Info.i_nproc; i++)
- X if (newproc[i].p_stat && getupage(newproc[i]))
- X {
- X j=i; /* record latest proc table location */
- X newusage[i] = User.u_us.u_ru;
- X if (oldproc[i].p_pid==newproc[i].p_pid)
- X {
- X time1 = oldusage[i].ru_utime.tv_sec +
- X oldusage[i].ru_stime.tv_sec;
- X utime1 = oldusage[i].ru_utime.tv_usec +
- X oldusage[i].ru_stime.tv_usec;
- X time2 = newusage[i].ru_utime.tv_sec +
- X newusage[i].ru_stime.tv_sec;
- X utime2 = newusage[i].ru_utime.tv_usec +
- X newusage[i].ru_stime.tv_usec;
- X p_delta = (time2*1000000+utime2) -
- X (time1*1000000+utime1);
- X if (p_delta)
- X {
- X s_delta = (nt.time*1000+nt.millitm) -
- X (ot.time*1000+ot.millitm);
- X pdata[k].pctcpu = (p_delta*10)/s_delta;
- X pdata[k].proc = &oldproc[i];
- X pdata[k].pr_cmd = i;
- X /*
- X
- X If you've settled on a reliable MAXACTIVE value,
- NOTE => you'll get a slight performance gain by replacing
- X the following if-statement with this line:
- X
- X k++;
- X
- X */
- X if (k < MAXACTIVE - 1)
- X k++;
- X else
- X printf("\ncputt: MAXACTIVE limit exceeded.\n");
- X }
- X }
- X else
- X {
- X getcmd(newproc[i],cmds[i]);
- X }
- X }
- X
- X /* check process table variance at each iteration */
- X
- X if (trim &&
- X (i-j < GROWTH_BUF - MAX_GROW || i-j > GROWTH_BUF + MAX_SHRINK))
- X {
- X printf("\nProcess table variance greater than %d, restarting..\n",
- X MAX_GROW + MAX_SHRINK);
- X execvp(argv[0],argv);
- X }
- X
- X /* sort and print results */
- X
- X qsort(pdata,k,sizeof(struct procdata),cmp);
- X printf("\n PID USER CPU MEM COMMANDS - %d %d\n",k,j);
- X for (i=--k; k>-1 && k>i-MAXOUT; --k)
- X {
- X printf("%5d ",pdata[k].proc->p_pid);
- X if (hp = hashuid(pdata[k].proc->p_suid))
- X printf("%-8.8s ", hp->h_uname);
- X else
- X printf("user%-4.4d ", pdata[k].proc->p_uid);
- X printf("%6.2f ",(float)pdata[k].pctcpu/100);
- X printf("%6.2f ",percentmem(pdata[k].proc));
- X printf(" %s\n",cmds[pdata[k].pr_cmd]);
- X }
- X
- X /* swap old and new pointers */
- X
- X tusage = oldusage; tproc = oldproc;
- X oldusage = newusage; oldproc = newproc;
- X newusage = tusage; newproc = tproc;
- X ot = nt;
- X
- X } /* for all iterations.. */
- X
- X} /* main */
- END_OF_FILE
- if test 7210 -ne `wc -c <'main.c'`; then
- echo shar: \"'main.c'\" unpacked with wrong size!
- fi
- # end of 'main.c'
- fi
- if test -f 'routines.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'routines.c'\"
- else
- echo shar: Extracting \"'routines.c'\" \(2758 characters\)
- sed "s/^X//" >'routines.c' <<'END_OF_FILE'
- X# include "cputt.h"
- X# include <varargs.h>
- X# include <kvm.h>
- X# include <stdio.h>
- X
- X/*
- X GETUPAGE - Reads the upage for the specified process as well as sufficient
- X page tables entries for reading the command arguments. The pte's are read
- X into the argument `p'. The upage is read into the external variable
- X `User'. Returns 1 if the upage was successfully read.
- X*/
- X
- getupage ( p )
- X
- register struct proc *p ;
- X
- X{
- X struct user *upage ;
- X extern union userstate User ;
- X extern kvm_t *Flkvm ;
- X
- X if (upage = kvm_getu( Flkvm, p ))
- X {
- X bcopy( (char *)upage, User.u_pg[0], sizeof( struct user ) ) ;
- X return ( 1 ) ;
- X }
- X/*
- X fprintf( stderr, "cputt - Can't read upage of process %d s= %o f= %o\n",
- X p->p_pid, p->p_stat, p->p_flag ) ;
- X*/
- X return ( 0 ) ;
- X}
- X
- X/* READSTATUS - Reads process table from kernel memory */
- X
- readstatus ( ptable )
- X
- struct proc *ptable;
- X
- X{
- X extern struct info Info ;
- X
- X if (getkmem((long)Info.i_proc0,(char*)ptable,Info.i_sproc) != Info.i_sproc)
- X {
- X fprintf(stderr,"cputt - Can't read system process table\n" ) ;
- X exit();
- X }
- X}
- X
- X/* PERCENTMEM - Returns the percentage of real memory used by this process */
- X
- double percentmem ( p )
- X
- struct proc *p ;
- X
- X{
- X double fracmem ;
- X extern struct info Info ;
- X
- X if ( !(p->p_flag & SLOAD) )
- X return ( 0.0 ) ;
- X fracmem = ( (double)p->p_rssize + UPAGES ) ;
- X return ( 100.0 * fracmem / (double)Info.i_ecmx ) ;
- X}
- X
- X/* GETKMEM - read kernel memory */
- X
- getkmem ( addr, buf, bufsize )
- X
- long addr ;
- char *buf ;
- int bufsize ;
- X{
- X extern kvm_t *Flkvm ;
- X
- X return( kvm_read( Flkvm, (long)addr, buf, bufsize ) ) ;
- X}
- X
- X/* SYSPERROR - Reports a system defined error msg and then exits gracefully */
- X
- sysperror ()
- X{
- X extern int errno ;
- X extern int sys_nerr ;
- X extern char *sys_errlist[] ;
- X
- X if ( 0 < errno && errno < sys_nerr )
- X fprintf( stderr, " : %s", sys_errlist[errno] ) ;
- X (void)fputc( '\n', stderr ) ;
- X exit( 1 ) ;
- X}
- X
- X/* GETCORE - Allocate and return a pointer to the asked for amount of core */
- X
- char *getcore ( size )
- X
- register int size ;
- X
- X{
- X register char *chp ;
- X char *malloc() ;
- X
- X if ( chp = malloc( (unsigned)size ) )
- X return ( chp ) ;
- X fprintf( stderr, "cputt - Out of core" ) ;
- X sysperror() ;
- X}
- X
- X/* CMP - used by qsort() to perform comparisons */
- X
- int cmp(p1,p2)
- X
- register struct procdata *p1, *p2;
- X
- X{
- X return (p1->pctcpu - p2->pctcpu);
- X}
- END_OF_FILE
- if test 2758 -ne `wc -c <'routines.c'`; then
- echo shar: \"'routines.c'\" unpacked with wrong size!
- fi
- # end of 'routines.c'
- fi
- echo shar: End of shell archive.
- exit 0
-