masscomp@soma.UUCP (06/15/86)
Here is my attempt to use cinfo. It is not perfect, but perhaps some of you can fix the problems that it has. Use cc -O cinfo.c -o cinfo -lm to compile. ============================================================== #include <stdio.h> #include <nlist.h> #include <pwd.h> #include <signal.h> #include <sys/param.h> #include <sys/pte.h> #include <sys/dir.h> #undef DIRSIZ #define DIRSIZ 14 #include <sys/minmax.h> #include <sys/cmap.h> #include <sys/text.h> #include <sys/cinfo.h> #include <sys/user.h> #include <sys/proc.h> #define MAX_CMAP 2048 #define MAX_PROC 300 #define MAX_TEXT 100 #define KMEM "/dev/kmem" #define MEM "/dev/mem" #define VMUNIX "/unix" static char rcsid[]= "$Header: cinfo.c,v 1.1 86/06/14 16:40:07 sob Exp $"; extern int errno; extern char * sys_errlist[]; struct nlist nlst[] = { { "_avenrun" }, #define X_AVENRUN 0 { "_ccpu" }, #define X_CCPU 1 { "_mpid" }, #define X_MPID 2 { "_freemem" }, #define X_FREEMEM 3 { 0 }, }; /* process state names for the "STATE" column of the display */ char *state_abbrev[] = { "", "sleep", "run", "WAIT", "idle", "", "","", "zomb","", "", "", "", "", "", "", "tired", "","", "","", "", }; struct proc proc_v[MAX_PROC]; struct text text_v[MAX_TEXT]; struct cmap cmap_v[MAX_CMAP]; struct user u; struct cu_des cu_des; short proc_count; short text_count; short cmap_count; int status,mem,kmem; char * username(); /* this program attempts to do something like ps on a Masscomp */ /* it seems to work fine on a 5600/5700 but stil has problems on a 5500 */ static char * copyright = "Copyright 1986 Stan Barber\n"; /* This program may be freely distributed in source or binary as long as no * sale is made of this program in any form. * Stan Barber assumes no liability for the use of this program good or bad. * Stan Barber makes no guarentees relating to the correctness of this program * for any use, intended or otherwise. * This program may be used as source for other works as long * as all material from the copyright statement to the end of this sentence * is retained in full without alteration. */ main() { struct proc *pp; int i,cputime; double pctcpu,logcpu,ccpu; /* open kmem and mem */ if ((kmem = open(KMEM, 0)) < 0) { perror(KMEM); exit(1); } if ((mem = open(MEM, 0)) < 0) { perror(MEM); exit(1); } nlist(VMUNIX,nlst); getkval(nlst[X_CCPU].n_value, &ccpu, sizeof(int), nlst[X_CCPU].n_name); logcpu = log(ccpu); while(1){ system("clear"); cu_des.p_max = MAX_PROC; cu_des.t_max = MAX_TEXT; cu_des.c_max = MAX_CMAP; status=cinfo(&cu_des,proc_v,text_v,cmap_v); if (status < 0){ perror("cinfo"); exit(-1); } proc_count = cu_des.p_ret; text_count = cu_des.t_ret; cmap_count = cu_des.c_ret; if (proc_count < 0 ){ fprintf(stderr,"warning: not enough proc_v entries\n"); proc_count = cu_des.p_max; } if (text_count < 0 ){ fprintf(stderr,"warning: not enough text_v entries\n"); text_count = cu_des.t_max; } if (cmap_count < 0 ){ fprintf(stderr,"warning: not enough cmap_v entries\n"); cmap_count = cu_des.c_max; } printf("\n PID USERNAME PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND\n"); for (i = 0; i < proc_count; i++) { pp = &proc_v[i]; if (pp->p_pid !=0){ if (getu(pp) == -1 || strlen(u.u_comm) == 0) { strcpy(u.u_comm, "<swapped>"); cputime = 0; } else { cputime = (u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec); } pctcpu = pp->p_pctcpu; printf("%5d %-8.8s %3d %4d%6dK %4dK %-5s%4d:%02d %5.2f%% %5.2f%% %-14.14s\n", pp->p_pid, getpwuid(pp->p_uid)->pw_name, pp->p_pri - PZERO, pp->p_nice - NZERO, (pp->p_tsize + pp->p_dsize + pp->p_ssize) >> 1, pp->p_rssize >> 1, state_abbrev[pp->p_stat], cputime / 60l, cputime % 60l, pp->p_time == 0 ? 0.0 : pctcpu / (1.0 - exp(pp->p_time * logcpu)), pctcpu, u.u_comm); } } sleep(5); } } /* * All of this stuff gets things out of the memory files. */ /* * Get the user structure for the process who's proc structure is in p. The * user structure is returned in u. */ getu(p) register struct proc *p; { struct pte uptes[UPAGES]; register caddr_t upage; register struct pte *pte; register nbytes, n; /* * Check if the process is currently loaded or swapped out. The way we * get the u area is totally different for the two cases. For this * application, we just don't bother if the process is swapped out. */ if ((p->p_flag & SLOAD) == 0) { return(-1); } /* * Process is currently in memory, we hope! */ if (!getkval(p->p_addr, uptes, sizeof(uptes), "p->p_addr")) { /* we can't seem to get to it, so pretend it's swapped out */ return(-1); } upage = (caddr_t)&u; pte = uptes; for (nbytes = sizeof(u); nbytes > 0; nbytes -= NBPG) { lseek(mem, pte++->pg_pfnum * NBPG, 0); n = MIN(nbytes, NBPG); if (read(mem, upage, n) != n) { /* we can't seem to get to it, so pretend it's swapped out */ return(-1); } upage += n; } return(0); } /* * get the value of something from /dev/kmem */ getkval(offset, ptr, size, refstr) long offset; int *ptr; int size; char *refstr; { if (lseek(kmem, offset, 0) == -1) { fprintf(stderr, "%s: lseek to %s: %s\n", KMEM, refstr, sys_errlist[errno]); exit(1); } if (read(kmem, ptr, size) == -1) { if (strcmp(refstr, "p->p_addr") == 0) { /* we lost the race with the kernel, process isn't in memory */ return(0); } else { fprintf(stderr, "%s: reading %s: %s\n", KMEM, refstr, sys_errlist[errno]); exit(1); } } return(1); }