📄 m_ftx.c
字号:
/* * top - a top users display for Unix * * SYNOPSIS: For FTX based System V Release 4 * * DESCRIPTION: * System V release 4.0.x for FTX (FTX 2.3 and greater) * * LIBS: -lelf * * AUTHORS: Andrew Herbert <andrew@werple.apana.org.au> * Robert Boucher <boucher@sofkin.ca> * Steve Scherf <scherf@swdc.stratus.com> */#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <errno.h>#include <dirent.h>#include <nlist.h>#include <string.h>#include <sys/types.h>#include <sys/param.h>#include <sys/procfs.h>#include <sys/sysmacros.h>#include <sys/sysinfo.h>#include <sys/vmmeter.h>#include <vm/anon.h>#include <sys/priocntl.h>#include <sys/rtpriocntl.h>#include <sys/tspriocntl.h>#include <sys/procset.h>#include <sys/var.h>#include <sys/tuneable.h>#include <sys/fs/rf_acct.h>#include <sys/sar.h>#include <sys/ftx/dcm.h>#include "top.h"#include "machine.h"#define UNIX "/unix"#define KMEM "/dev/kmem"#define PROCFS "/proc"#define SAR "/dev/sar"#define CPUSTATES 5#ifndef PRIO_MAX#define PRIO_MAX 20#endif#ifndef PRIO_MIN#define PRIO_MIN -20#endif#ifndef FSCALE#define FSHIFT 8 /* bits to right of fixed binary point */#define FSCALE (1<<FSHIFT)#endif#define loaddouble(x) ((double)(x) / FSCALE)#define pagetok(size) ctob(size) >> LOG1024#define PRTOMS(pp) \ ((pp)->pr_time.tv_sec * 1000) + ((pp)->pr_time.tv_nsec / 1000000)/* definitions for the index in the nlist array */#define X_AVENRUN 0#define X_MPID 1#define X_V 2#define X_NPROC 3#define X_ANONINFO 4#define X_TOTAL 5static struct nlist nlst[] ={ {"avenrun"}, /* 0 */ {"mpid"}, /* 1 */ {"v"}, /* 2 */ {"nproc"}, /* 3 */ {"anoninfo"}, /* 4 */ {"total"}, /* 5 */ {NULL}};static unsigned long avenrun_offset;static unsigned long mpid_offset;static unsigned long nproc_offset;static unsigned long anoninfo_offset;static unsigned long total_offset;/* get_process_info passes back a handle. This is what it looks like: */struct handle { struct prpsinfo **next_proc;/* points to next valid proc pointer */ int remaining; /* number of pointers remaining */ };#define MAXTIMEHIST 12#define HASHSZ 512 /* This must be a power of 2. */#define HASHMASK (HASHSZ - 1)#define TF_USED 0x01#define TF_NEWPROC 0x02#define TD_HASH(pid) \ (timedata_t *)(&hash[(pid) & HASHMASK])typedef struct hash { struct timedata *hnext; struct timedata *hlast;} hash_t;/* data for CPU and WCPU fields */typedef struct timedata { struct timedata *hnext; struct timedata *hlast; struct timedata *lnext; struct timedata *llast; pid_t pid; char index; char cnt; char flags; long hist[MAXTIMEHIST]; long time; long ltime;} timedata_t;/* * These definitions control the format of the per-process area */static char header[] =" PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND";/* 0123456 -- field to fill in starts at header+6 */#define UNAME_START 6#define Proc_format \ "%5d %-8.8s %3d %4d%6dK %4dK %-5s%4d:%02d %5.2f%% %5.2f%% %.16s"char *state_abbrev[] ={"", "sleep", "run", "zombie", "stop", "start", "cpu", "swap"};int process_states[8];char *procstatenames[] ={ "", " sleeping, ", " running, ", " zombie, ", " stopped, ", " starting, ", " on cpu, ", " swapped, ", NULL};int cpu_states[CPUSTATES];char *cpustatenames[] ={"idle", "user", "kernel", "wait", "swap", NULL};/* these are for detailing the memory statistics */int memory_stats[5];char *memorynames[] ={"K real, ", "K active, ", "K free, ", "K swap, ", "K free swap", NULL};static int kmem;static int sar;static int initted;static int nproc;static int bytes;static struct prpsinfo *pbase;static struct prpsinfo **pref;static DIR *procdir;static char cpu_state[MAX_LOG_CPU];static struct sysinfo cpu_sysinfo[MAX_LOG_CPU];static sar_percpu_args_t spa;static timedata_t timedata;static long total_time;static double total_cpu;static hash_t hash[HASHSZ];/* useful externals */extern int errno;extern char *sys_errlist[];extern char *myname;extern long percentages ();extern int check_nlist ();extern int getkval ();extern void perror ();extern void getptable ();extern void quit ();extern int nlist ();/* Prototypes. */void getsysinfo(struct sysinfo *);void add_time(struct prpsinfo *);void get_cpu(struct prpsinfo *, double *, double *);void clean_timedata(void);timedata_t *get_timedata(struct prpsinfo *);intmachine_init (struct statics *statics) { int i; static struct var v; /* fill in the statics information */ statics->procstate_names = procstatenames; statics->cpustate_names = cpustatenames; statics->memory_names = memorynames; /* get the list of symbols we want to access in the kernel */ if (nlist (UNIX, nlst)) { (void) fprintf (stderr, "Unable to nlist %s\n", UNIX); return (-1); } /* make sure they were all found */ if (check_nlist (nlst) > 0) return (-1); /* open kernel memory */ if ((kmem = open (KMEM, O_RDONLY)) == -1) { perror (KMEM); return (-1); } /* Open the sar driver device node. */ if ((sar = open(SAR, O_RDONLY)) == -1) { perror (SAR); return (-1); } /* get the symbol values out of kmem */ /* NPROC Tuning parameter for max number of processes */ (void) getkval (nlst[X_V].n_value, &v, sizeof (struct var), nlst[X_V].n_name); nproc = v.v_proc; /* stash away certain offsets for later use */ mpid_offset = nlst[X_MPID].n_value; nproc_offset = nlst[X_NPROC].n_value; avenrun_offset = nlst[X_AVENRUN].n_value; anoninfo_offset = nlst[X_ANONINFO].n_value; total_offset = nlst[X_TOTAL].n_value; /* allocate space for proc structure array and array of pointers */ bytes = nproc * sizeof (struct prpsinfo); pbase = (struct prpsinfo *) malloc (bytes); pref = (struct prpsinfo **) malloc (nproc * sizeof (struct prpsinfo *)); /* Just in case ... */ if (pbase == (struct prpsinfo *) NULL || pref == (struct prpsinfo **) NULL) { (void) fprintf (stderr, "%s: can't allocate sufficient memory\n", myname); return (-1); } if (!(procdir = opendir (PROCFS))) { (void) fprintf (stderr, "Unable to open %s\n", PROCFS); return (-1); } if (chdir (PROCFS)) { /* handy for later on when we're reading it */ (void) fprintf (stderr, "Unable to chdir to %s\n", PROCFS); return (-1); } /* Set up the pointers to the sysinfo data area. */ spa.uvcp = (caddr_t) &cpu_state[0]; spa.uvsp = (caddr_t) &cpu_sysinfo[0]; timedata.lnext = &timedata; timedata.llast = &timedata; for (i = 0; i < HASHSZ; i++) { hash[i].hnext = (timedata_t *)&hash[i]; hash[i].hlast = (timedata_t *)&hash[i]; } /* all done! */ return (0); }char *format_header (char *uname_field){ register char *ptr; ptr = header + UNAME_START; while (*uname_field != '\0') *ptr++ = *uname_field++; return (header);}voidget_system_info (struct system_info *si){ long avenrun[3]; struct sysinfo sysinfo; struct vmtotal total; struct anoninfo anoninfo; static time_t cp_old[CPUSTATES]; static time_t cp_diff[CPUSTATES]; /* for cpu state percentages */ register int i; getsysinfo(&sysinfo); /* convert cp_time counts to percentages */ (void) percentages (CPUSTATES, cpu_states, sysinfo.cpu, cp_old, cp_diff); /* Find total CPU utilization, as a fraction of 1. */ total_cpu = (cpu_states[CPU_USER] + cpu_states[CPU_KERNEL]) / 1000.0; /* get mpid -- process id of last process */ (void) getkval (mpid_offset, &(si->last_pid), sizeof (si->last_pid), "mpid"); /* get load average array */ (void) getkval (avenrun_offset, (int *) avenrun, sizeof (avenrun), "avenrun"); /* convert load averages to doubles */ for (i = 0; i < 3; i++) si->load_avg[i] = loaddouble (avenrun[i]); /* get total -- systemwide main memory usage structure */ (void) getkval (total_offset, (int *) (&total), sizeof (total), "total"); /* convert memory stats to Kbytes */ memory_stats[0] = pagetok (total.t_rm); memory_stats[1] = pagetok (total.t_arm); memory_stats[2] = pagetok (total.t_free); (void) getkval (anoninfo_offset, (int *) (&anoninfo), sizeof (anoninfo), "anoninfo"); memory_stats[3] = pagetok (anoninfo.ani_max - anoninfo.ani_free); memory_stats[4] = pagetok (anoninfo.ani_max - anoninfo.ani_resv); /* set arrays and strings */ si->cpustates = cpu_states; si->memory = memory_stats;}static struct handle handle;caddr_tget_process_info ( struct system_info *si, struct process_select *sel, int (*compare) ()){ register int i; register int total_procs; register int active_procs; register struct prpsinfo **prefp; register struct prpsinfo *pp; /* these are copied out of sel for speed */ int show_idle; int show_system; int show_uid; /* Get current number of processes */ (void) getkval (nproc_offset, (int *) (&nproc), sizeof (nproc), "nproc"); /* read all the proc structures */ getptable (pbase); /* get a pointer to the states summary array */ si->procstates = process_states; /* set up flags which define what we are going to select */ show_idle = sel->idle; show_system = sel->system; show_uid = sel->uid != -1; /* count up process states and get pointers to interesting procs */ total_procs = 0; active_procs = 0; total_time = 0; (void) memset (process_states, 0, sizeof (process_states)); prefp = pref; clean_timedata(); for (pp = pbase, i = 0; i < nproc; pp++, i++) { /* * Place pointers to each valid proc structure in pref[]. * Process slots that are actually in use have a non-zero * status field. Processes with SSYS set are system * processes---these get ignored unless show_sysprocs is set. */ if (pp->pr_state != 0 && (show_system || ((pp->pr_flag & SSYS) == 0))) { total_procs++; process_states[pp->pr_state]++; if ((!pp->pr_zomb) && (show_idle || (pp->pr_state == SRUN) || (pp->pr_state == SONPROC)) && (!show_uid || pp->pr_uid == (uid_t) sel->uid)) { *prefp++ = pp; active_procs++; } } if (pp->pr_state != 0) add_time(pp); } /* Note that we've run this at least once. */ initted++; /* if requested, sort the "interesting" processes */ if (compare != NULL) qsort ((char *) pref, active_procs, sizeof (struct prpsinfo *), compare); /* remember active and total counts */ si->p_total = total_procs; si->p_active = active_procs; /* pass back a handle */ handle.next_proc = pref; handle.remaining = active_procs; return ((caddr_t) & handle);}char fmt[128]; /* static area where result is built */char *format_next_process ( caddr_t handle, char *(*get_userid) ()){ register struct prpsinfo *pp; struct handle *hp; register long cputime; double pctcpu; double pctwcpu; /* find and remember the next proc structure */ hp = (struct handle *) handle; pp = *(hp->next_proc++);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -