home *** CD-ROM | disk | FTP | other *** search
- #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 */
-