home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume26
/
cputt
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-18
|
7KB
|
201 lines
#include "cputt.h"
#include <kvm.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <sys/resource.h>
/*
MAIN - Computes CPU utilization for all processes from two snapshots
of the kernel process table taken over a user supplied interval
(arg1). Sorts and prints the top ten CPU using processes for that
interval. Execution continues for a user supplied number of
iterations (arg2).
The kernel process table snapshots are stored in two arrays,
'oldproc' and 'newproc'. Resource utilization information is stored
in two arrays, 'oldusage' and 'newusage'. The command strings for
each process are stored in a 2D array, 'cmds'. CPU utilization for
each interval is stored in the 'pdata' array along with pointers to
the appropriate 'proc' and 'cmds' entries.
*/
main (argc, argv)
int argc; char *argv[];
{
extern struct info Info;
extern kvm_t *Flkvm;
extern union userstate User;
struct proc *oldproc,*newproc,*tproc;
struct rusage *oldusage,*newusage,*tusage;
struct procdata *pdata;
struct hashtab *hp;
register long time1,utime1,time2,utime2;
register long s_delta, p_delta;
register int i,j,k;
struct timeb ot,nt;
struct hashtab *hashuid();
int trim=0,reps,cmp();
double percentmem();
char **cmds;
if (argc != 3)
{
printf("usage: cputt <interval> <iterations>\n");
exit();
}
setpriority(PRIO_PROCESS,0,-20);
/* open kernel memory */
Flkvm = kvm_open(NULL, NULL, NULL, O_RDONLY, "cputt");
/* get critical system parameters, build uid hash table */
init();
initusers();
/* truncate unused portion of the process table */
Info.i_sproc = Info.i_nproc * sizeof(struct proc);
if (GROWTH_BUF)
{
oldproc = (struct proc *) getcore(Info.i_nproc*sizeof(struct proc));
readstatus(oldproc);
for (i=0; i<Info.i_nproc; i++)
if (oldproc[i].p_stat && getupage(oldproc[i]))
j=i;
free(oldproc);
if (j+GROWTH_BUF < Info.i_nproc)
{
Info.i_nproc = j+GROWTH_BUF;
Info.i_sproc = Info.i_nproc * sizeof(struct proc);
trim = 1;
}
}
/* allocate core for internal data structures */
cmds = (char **) getcore(Info.i_nproc*sizeof(char *));
for (i=0;i<Info.i_nproc;i++)
cmds[i] = (char *) getcore(COMMAND_SIZE);
pdata = (struct procdata *)
getcore(MAXACTIVE*sizeof(struct procdata));
oldusage = (struct rusage *)
getcore(Info.i_nproc*sizeof(struct rusage));
newusage = (struct rusage *)
getcore(Info.i_nproc*sizeof(struct rusage));
oldproc = (struct proc *) getcore(Info.i_nproc*sizeof(struct proc));
newproc = (struct proc *) getcore(Info.i_nproc*sizeof(struct proc));
/* get initial time, process table, upage, and command strings */
ftime(&ot);
readstatus(oldproc);
for (i=0;i<Info.i_nproc;i++)
if (oldproc[i].p_stat && getupage(oldproc[i]))
{
oldusage[i] = User.u_us.u_ru;
getcmd(oldproc[i],cmds[i]);
}
/* compare process tables every argv[1] seconds for argv[2] iterations */
for (reps = 0; reps < atoi(argv[2]); reps++)
{
sleep(atoi(argv[1])); /* sleep for agrv[1] seconds */
ftime(&nt); /* get new time */
readstatus(newproc); /* get new process table */
/* find matching pids, compute cpu usage, store results in pdata */
for (i=k=0; i<Info.i_nproc; i++)
if (newproc[i].p_stat && getupage(newproc[i]))
{
j=i; /* record latest proc table location */
newusage[i] = User.u_us.u_ru;
if (oldproc[i].p_pid==newproc[i].p_pid)
{
time1 = oldusage[i].ru_utime.tv_sec +
oldusage[i].ru_stime.tv_sec;
utime1 = oldusage[i].ru_utime.tv_usec +
oldusage[i].ru_stime.tv_usec;
time2 = newusage[i].ru_utime.tv_sec +
newusage[i].ru_stime.tv_sec;
utime2 = newusage[i].ru_utime.tv_usec +
newusage[i].ru_stime.tv_usec;
p_delta = (time2*1000000+utime2) -
(time1*1000000+utime1);
if (p_delta)
{
s_delta = (nt.time*1000+nt.millitm) -
(ot.time*1000+ot.millitm);
pdata[k].pctcpu = (p_delta*10)/s_delta;
pdata[k].proc = &oldproc[i];
pdata[k].pr_cmd = i;
/*
If you've settled on a reliable MAXACTIVE value,
NOTE => you'll get a slight performance gain by replacing
the following if-statement with this line:
k++;
*/
if (k < MAXACTIVE - 1)
k++;
else
printf("\ncputt: MAXACTIVE limit exceeded.\n");
}
}
else
{
getcmd(newproc[i],cmds[i]);
}
}
/* check process table variance at each iteration */
if (trim &&
(i-j < GROWTH_BUF - MAX_GROW || i-j > GROWTH_BUF + MAX_SHRINK))
{
printf("\nProcess table variance greater than %d, restarting..\n",
MAX_GROW + MAX_SHRINK);
execvp(argv[0],argv);
}
/* sort and print results */
qsort(pdata,k,sizeof(struct procdata),cmp);
printf("\n PID USER CPU MEM COMMANDS - %d %d\n",k,j);
for (i=--k; k>-1 && k>i-MAXOUT; --k)
{
printf("%5d ",pdata[k].proc->p_pid);
if (hp = hashuid(pdata[k].proc->p_suid))
printf("%-8.8s ", hp->h_uname);
else
printf("user%-4.4d ", pdata[k].proc->p_uid);
printf("%6.2f ",(float)pdata[k].pctcpu/100);
printf("%6.2f ",percentmem(pdata[k].proc));
printf(" %s\n",cmds[pdata[k].pr_cmd]);
}
/* swap old and new pointers */
tusage = oldusage; tproc = oldproc;
oldusage = newusage; oldproc = newproc;
newusage = tusage; newproc = tproc;
ot = nt;
} /* for all iterations.. */
} /* main */