📄 m_svr42mp.c
字号:
/* * top - a top users display for Unix * * SYNOPSIS: For Intel based SysVr4.2MP (UnixWare 2) * * DESCRIPTION: * System V release 4.2MP for i?86 (UnixWare2) * * LIBS: -lelf * * CFLAGS: -DHAVE_GETOPT -DORDER * AUTHOR: Daniel Harris <daniel@greencape.com.au> * Mike Hopkirk <hops@sco.com> * * BASED ON: Most of the work in this module is attributable to the * authors of m_svr42.c and m_sunos5.c. (Thanks!) * * Originally written by Daniel Green as an implementation for * Unixware7 (sysVr5) * Incomplete for that but applied by Mike Hopkirk to svr4.2MP * for which there was not a working port available. * * NOTES: * * You shouldn't make this setuid anything. It doesn't flip between * saved uids. * * This module looks nothing like other top modules. In my deluded * world, function follows form. Code needs to look good in order * to work. :-) Apologies to anyone offended by by reformatting. * * The number of processes is calculated by the number of entries in the * /proc filesystem. * * sysinfo structure should be available from the kernel in preference * to following met_localdata_ptrs_p but if so its naming is obscure. * * Ordering of tasks other than by the default isn't implemented yet. * * Nice value is always displayed as 0 due bug in UW2 * * * DATE CHANGE * 03/09/1998 Couple of comment changes. Prepare for release. * 13/06/1998 Cleaned out debugging code, prepared for limited release. * 09/07/1999 Modified for UnixWare 2 (2.1.2) build - hops * Added use of system getopt and additional sort orders * *//* ************************************************************************** *//* build config * SHOW_NICE - process nice fields always accessed as 0 so changed * default to display # of threads in use instead. * define this to display nice fields (values always 0) * #define SHOW_NICE 1 *//* * Defines */#define _KMEMUSER /* Needed to access appropriate system include file */ /* structures. */#define UNIX "/unix" /* Miscellaneous paths. */#define PROCFS "/proc"#define PATH_KMEM "/dev/kmem"/* * Maximum and minumum priorities. */#ifndef PRIO_MAX#define PRIO_MAX 20#endif#ifndef PRIO_MIN#define PRIO_MIN -20#endif/* * Scaling factor used to adjust kernel load average numbers. * Unixware note: as I can't find any documentation on the avenrun * symbol, I'm not entirely sure if this is correct. */#ifndef FSCALE#define FSHIFT 8 /* bits to right of fixed binary point */#define FSCALE (1<<FSHIFT)#endif/* Macro to convert between avenrun load average numbers and normal *//* load average. */#define loaddouble(x) ((double)(x) / FSCALE)/* Convert number of pages to size in kB. */#define pagetok(size) ((size * PAGESIZE) >> 10)/* * Unixware doesn't explicitly track zombie processes. * However, they can be identified as processes with no threads. * Also, define an additional artificial process state to keep * track of how many zombies there are. */#define ZOMBIE(z) ((z)->p.p_nlwp == 0)#define ZOMBIESTATE 6/* * Definitions for the index in the nlist array. */#define X_AVENRUN 0#define X_NEXTPID 1#define X_V 2#define X_OFFSETS 3#define X_TOTALMEM 4/* * Hash function for the table of processes used to keep old information. */#define HASH(x) ((x << 1) % numoldprocs)/* ************************************************************************** *//* * Include files */#include "utils.h"#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/proc.h>#include <sys/procfs.h>#include <sys/sysinfo.h>#include <sys/sysmacros.h>#include <sys/vmmeter.h>#include <sys/ksym.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/metrics.h>#include <sys/time.h>#include "top.h"#include "machine.h"/* ************************************************************************** *//* * Structures *//* * A process is just a thread container under Unixware. * So, define the following structure which will aggregate * most of what we want. */struct uwproc{ int dummy; struct psinfo ps; struct proc p; struct lwp l; double pctcpu; double wcpu;};/* defines to simplify access to some of contents of uwproc struct */#define PR_pri ps.pr_lwp.pr_pri#define PR_state ps.pr_lwp.pr_state#define PR_time ps.pr_lwp.pr_time/* * oldproc * Oldproc is used to hold process CPU history necessary to * calculate %CPU and WCPU figures. */struct oldproc{ int oldpid; double oldtime; /* Duration of process in ns. */ double oldpct;};/* * nlist * An array of the kernel sybols used by this module. */static struct nlist nlst[] ={ {"avenrun"}, /* 0 X_AVENRUN */ {"nextpid"}, /* 1 X_NEXTPID */ {"v"}, /* 2 X_V */ {"met_localdata_ptrs_p"}, /* 3 X_OFFSETS */ {"totalmem"}, /* 4 X_TOTALMEM */ {NULL}};/* * Get_process_info passes back a handle. This is what it looks like: */struct handle{ struct uwproc **next_proc; /* points to next valid proc pointer */ int remaining; /* number of pointers remaining */};/* ************************************************************************** *//* * Globals */static unsigned long avenrun_offset;static unsigned long nextpid_offset;static unsigned long v_offset;static unsigned long offset_offset;static unsigned long totalmem_offset;static int kmem = -1; /* FD to /dev/kmem. */static int maxprocs; /* Maximum number of processes that */ /* can be running on the system. */static int numoldprocs; /* Size of oldproc hash. */static int numprocs = 0; /* Number of processes currently */ /* running on the system. Updated */ /* each time getptable() is called. */static int bytes; /* Size of array of process structs. */static struct uwproc *pbase; /* Pointer to array of process info. */static struct uwproc **pref; /* Vector of uwbase pointers. */static struct oldproc *oldbase; /* Pointer to array of old proc info. */static DIR *procdir;extern int errno;extern char *myname;/* * An abbreviation of the states each process may be in. */char *state_abbrev[] = { "oncpu", "run", "sleep", "stop", "idle", "zomb", NULL};/* * The states each process may be in. */int process_states[6];char *procstatenames[] ={ " on cpu, ", " running, ", " sleeping, ", " stopped, ", " idle, ", " zombie", NULL};/* * CPU usage tracked by the kernel. */#define CPUSTATES 4int cpu_states[CPUSTATES];char *cpustatenames[] = {"idle", "wait", "user", "sys", NULL};/* * These are for detailing the memory statistics. */int memory_stats[3];char *memorynames[] = {"K phys, ", "K swap, ", "K swap free", NULL};/* * These definitions control the format of the per-process area */static char header[] =#ifdef SHOW_NICE " PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND";#else " PID X PRI THR SIZE RES STATE TIME WCPU CPU COMMAND";#endif/* 0123456 -- field to fill in starts at header+6 */ /* XXXX */#define UNAME_START 6#define PROC_FORMAT "%5d %-8.8s %3d %4d %5s %5s %-5s %6s %5.2f%% %5.2f%% %s"/* these are names given to allowed sorting orders -- first is default */char *ordernames[] = {"cpu", "state", "size", "res", "time", "pid", "uid", "rpid", "ruid", NULL};/* ************************************************************************** *//* * Prototypes */int machine_init(struct statics *);char *format_header(char *);void get_system_info(struct system_info *);caddr_t get_process_info(struct system_info *, struct process_select *, int (*)());char *format_next_process(caddr_t, char *(*)());int check_nlist(register struct nlist *);int getkval(unsigned long, void *, int, char *);int proc_compare(void *, void *);void getptable(struct uwproc *);uid_t proc_owner(pid_t);int setpriority(int, int, int);void get_swapinfo(long *, long *);/* forward definitions for comparison functions */int compare_state(void *, void *);int compare_cpu(void *, void *);int compare_size(void *, void *);int compare_res(void *, void *);int compare_time(void *, void *);int compare_pid(void *, void *);int compare_uid(void *, void *);int compare_rpid(void *, void *);int compare_ruid(void *, void *);int (*proc_compares[])() = { compare_cpu, compare_state, compare_size, compare_res, compare_time, compare_pid, compare_uid, compare_rpid, compare_ruid, NULL };extern long percentages ();extern void quit ();/* ************************************************************************** *//* * machine_int * Perform once-off initialisation tasks. */intmachine_init (struct statics *statics){ static struct var v; struct oldproc *op; int i; /* * Fill in the statics information. */ statics->procstate_names = procstatenames; statics->cpustate_names = cpustatenames; statics->memory_names = memorynames; statics->order_names = ordernames; /* * Go through the kernel symbols required for this * module, and check that they are available. */ if (nlist (UNIX, nlst)) { fprintf (stderr, "Unable to nlist %s\n", UNIX); return -1; } /* * Make sure they were all found. */ if (check_nlist (nlst) > 0) return -1; /* * Open KMEM device for future use. */ kmem = open(PATH_KMEM, O_RDONLY); if (kmem == -1) { perror(PATH_KMEM); return -1; } /* * Extract the maximum number of running processes. */ getkval(nlst[X_V].n_value, (void *)&v, sizeof(v), nlst[X_V].n_name); maxprocs = v.v_proc; /* * Save pointers. */ avenrun_offset = nlst[X_AVENRUN].n_value; nextpid_offset = nlst[X_NEXTPID].n_value; v_offset = nlst[X_V].n_value; offset_offset = nlst[X_OFFSETS].n_value; totalmem_offset = nlst[X_TOTALMEM].n_value; /* * Allocate space for proc structure array and array of pointers. */ bytes = maxprocs * sizeof (struct uwproc); pbase = (struct uwproc *) malloc (bytes); pref = (struct uwproc **) malloc (maxprocs * sizeof (struct uwproc *)); numoldprocs = maxprocs * 2; oldbase = (struct oldproc *)malloc(numoldprocs * sizeof(struct oldproc)); if (pbase == (struct uwproc *) NULL || pref == (struct uwproc **) NULL || oldbase == (struct oldproc *) NULL) { fprintf(stderr, "%s: can't allocate sufficient memory\n", myname); return -1; } /* * Obtain a handle on the /proc filesystem, and change into it. */ if (!(procdir = opendir (PROCFS))) { fprintf (stderr, "Unable to open %s\n", PROCFS); return -1; } if (chdir (PROCFS)) { fprintf (stderr, "Unable to chdir to %s\n", PROCFS); return -1; } /* * Initialise the oldproc structures. */ for (op = oldbase, i = 0; i < numoldprocs; i++) { op[i].oldpid = -1; } /* * All done! */ return (0);}/* ************************************************************************** *//* * format_header */char *format_header (char *uname_field){ register char *ptr; ptr = header + UNAME_START; while (*uname_field != '\0') *ptr++ = *uname_field++; return (header);}/* ************************************************************************** *//* * Extract information out of system data structures. */voidget_system_info (struct system_info *si){ long avenrun[3]; static time_t cp_old[CPUSTATES]; static time_t cp_diff[CPUSTATES];/*for cpu state percentages*/ register int i; struct met_localdata_ptrs *mlpp; struct met_localdata_ptrs mlp; struct plocalmet plm; struct metp_cpu mc; unsigned long totalmem; long totalswap; long totalswapfree;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -