⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 m_decosf1.c

📁 unix系统下top命令的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * top - a top users display for Unix * * SYNOPSIS:  OSF/1, Digital Unix 4.0, Compaq Tru64 5.0 * * DESCRIPTION: * This is the machine-dependent module for DEC OSF/1 and its descendents * It is known to work on OSF/1 1.2, 1.3, 2.0-T3, 3.0, Digital Unix V4.0, * Digital Unix 5.0, and Tru64 5.0. * WARNING: if you use optimization with the standard "cc" compiler that * .        comes with V3.0 the resulting executable may core dump.  If * .        this happens, recompile without optimization. * * LIBS: -lmld -lmach * * CFLAGS: -DHAVE_GETOPT -DORDER * * AUTHOR:  Anthony Baxter, <anthony@aaii.oz.au> * Derived originally from m_ultrix, by David S. Comay <dsc@seismo.css.gov>,  * although by now there is hardly any of the code from m_ultrix left. * Helped a lot by having the source for syd(1), by Claus Kalle, and * from several people at DEC who helped with providing information on * some of the less-documented bits of the kernel interface. * * Modified: 31-Oct-94, Pat Welch, tpw@physics.orst.edu *	changed _mpid to pidtab for compatibility with OSF/1 version 3.0 * * Modified: 13-Dec-94, William LeFebvre, lefebvre@dis.anl.gov *	removed used of pidtab (that was bogus) and changed things to *	automatically detect the absence of _mpid in the nlist and *	recover gracefully---this appears to be the only difference *	with 3.0. * * Modified: 3-Mar-00, Rainer Orth <ro@TechFak.Uni-Bielefeld.DE> *	added support for sort ordering. *//*  * Theory of operation:  *  * Use Mach calls to build up a structure that contains all the sorts * of stuff normally found in a struct proc in a BSD system. Then * everything else uses this structure. This has major performance wins, * and also should work for future versions of the O/S. */#include <sys/types.h>#include <sys/signal.h>#include <sys/param.h>#include <string.h>#include <sys/user.h>#include <stdio.h>#include <nlist.h>#include <math.h>#include <sys/dir.h>#include <sys/user.h>#include <sys/proc.h>#include <sys/dk.h>#include <sys/vm.h>#include <sys/file.h>#include <sys/time.h>/* #include <machine/pte.h> *//* forward declarations, needed by <net/if.h> included from <sys/table.h> */struct rtentry;struct mbuf;#include <sys/table.h>#include <mach.h>#include <mach/mach_types.h>#include <mach/vm_statistics.h>#include <sys/syscall.h> /* for SYS_setpriority, in setpriority(), below */#include "top.h"#include "machine.h"#include "utils.h"extern int errno, sys_nerr;extern char *sys_errlist[];#define strerror(e) (((e) >= 0 && (e) < sys_nerr) ? sys_errlist[(e)] : "Unknown error")#define VMUNIX	"/vmunix"#define KMEM	"/dev/kmem"#define MEM	"/dev/mem"/* get_process_info passes back a handle.  This is what it looks like: */struct handle{    struct osf1_top_proc **next_proc;	/* points to next valid proc pointer */    int remaining;		/* number of pointers remaining */};/* declarations for load_avg */#include "loadavg.h"/* definitions for indices in the nlist array */#define X_MPID		0static struct nlist nlst[] = {    { "_mpid" },		/* 0 */    { 0 }};/* Some versions of OSF/1 don't support reporting of the last PID.   This flag indicates whether or not we are reporting the last PID. */static int do_last_pid = 1;/* *  These definitions control the format of the per-process area */static char header[] =  "  PID X        PRI NICE  SIZE   RES STATE   TIME    CPU COMMAND";/* 0123456   -- field to fill in starts at header+6 */#define UNAME_START 6#define Proc_format \	"%5d %-8.8s %3d %4d %5s %5s %-5s %-6s %5.2f%% %.14s"/* process state names for the "STATE" column of the display *//* the extra nulls in the string "run" are for adding a slash and * the processor number when needed. Although OSF/1 doesnt support * multiple processors yet, (and this module _certainly_ doesnt * support it, either, we may as well plan for the future. :-) */char *state_abbrev[] ={    "", "run\0\0\0", "WAIT", "sleep", "sleep", "stop", "halt", "???", "zomb"};static int kmem, mem;/* values that we stash away in _init and use in later routines */static double logcpu;/* these are retrieved from the kernel in _init */static unsigned long proc;static          int  nproc;static load_avg  ccpu;typedef long mtime_t;/* these are offsets obtained via nlist and used in the get_ functions */static unsigned long mpid_offset;/* these are for detailing the process states */int process_states[9];char *procstatenames[] = {    "", " running, ", " waiting, ", " sleeping, ", " idle, ",    " stopped, ", " halted, ", "", " zombie",    NULL};/* these are for detailing the cpu states */int cpu_states[4];char *cpustatenames[] = {    "user", "nice", "system", "idle", NULL};long old_cpu_ticks[4];/* these are for detailing the memory statistics */int memory_stats[8];char *memorynames[] = {    "Real: ", "K/", "K act/tot  ", "Virtual: ", "M/",    "M use/tot  ", "Free: ", "K", NULL};/* these are names given to allowed sorting orders -- first is default */char *ordernames[] = {    "cpu", "size", "res", "time", NULL};/* forward definitions for comparison functions */int compare_cpu();int compare_size();int compare_res();int compare_time();int (*proc_compares[])() = {    compare_cpu,    compare_size,    compare_res,    compare_time,    NULL};/* these are for getting the memory statistics */static int pageshift;		/* log base 2 of the pagesize *//* define pagetok in terms of pageshift */#define pagetok(size) ((size) << pageshift)/* take a process, make it a mach task, and grab all the info out */void do_threads_calculations();/* * Because I dont feel like repeatedly grunging through the kernel with * Mach calls, and I also dont want the horrid performance hit this * would give, I read the stuff I need out, and put in into my own * structure, for later use. */struct osf1_top_proc {    size_t p_mach_virt_size;    char p_mach_state;    int p_flag;    fixpt_t p_mach_pct_cpu; /* aka p_pctcpu */    int used_ticks;    size_t process_size;    pid_t p_pid;    uid_t p_ruid;    char p_pri;    char p_nice;    size_t p_rssize;    char u_comm[PI_COMLEN + 1];} ;/* these are for keeping track of the proc array */static int bytes;static int pref_len;static struct osf1_top_proc *pbase;static struct osf1_top_proc **pref;/* useful externals */extern int errno;extern char *sys_errlist[];long percentages();machine_init(statics)struct statics *statics;{    register int i = 0;    register int pagesize;    struct tbl_sysinfo sibuf;    if ((kmem = open(KMEM, O_RDONLY)) == -1) {	perror(KMEM);	return(-1);    }    if ((mem = open(MEM, O_RDONLY)) == -1) {	perror(MEM);	return(-1);    }    /* get the list of symbols we want to access in the kernel */    if (nlist(VMUNIX, nlst) == -1)    {	perror("TOP(nlist)");	return (-1);    }    if (nlst[X_MPID].n_type == 0)    {	/* this kernel has no _mpid, so go without */	do_last_pid = 0;    }    else    {	/* stash away mpid pointer for later use */	mpid_offset = nlst[X_MPID].n_value;    }    /* get the symbol values out of kmem */    nproc  = table(TBL_PROCINFO, 0, (struct tbl_procinfo *)NULL, INT_MAX, 0);    /* allocate space for proc structure array and array of pointers */    bytes = nproc * sizeof(struct osf1_top_proc);    pbase = (struct osf1_top_proc *)malloc(bytes);    pref  = (struct osf1_top_proc **)malloc(nproc *                                               sizeof(struct osf1_top_proc *));    /* Just in case ... */    if (pbase == (struct osf1_top_proc *)NULL ||                                   pref == (struct osf1_top_proc **)NULL)    {	fprintf(stderr, "top: cannot allocate sufficient memory\n");	return(-1);    }    /* get the page size with "getpagesize" and calculate pageshift from it */    pagesize = getpagesize();    pageshift = 0;    while (pagesize > 1)    {	pageshift++;	pagesize >>= 1;    }    /* we only need the amount of log(2)1024 for our conversion */    pageshift -= LOG1024;    /* fill in the statics information */    statics->procstate_names = procstatenames;    statics->cpustate_names = cpustatenames;    statics->memory_names = memorynames;    statics->order_names = ordernames;    /* initialise this, for calculating cpu time */    if (table(TBL_SYSINFO,0,&sibuf,1,sizeof(struct tbl_sysinfo))<0) {	perror("TBL_SYSINFO");	return(-1);    }    old_cpu_ticks[0] = sibuf.si_user;    old_cpu_ticks[1] = sibuf.si_nice;    old_cpu_ticks[2] = sibuf.si_sys;    old_cpu_ticks[3] = sibuf.si_idle;    /* all done! */    return(0);}char *format_header(uname_field)register char *uname_field;{    register char *ptr;    ptr = header + UNAME_START;    while (*uname_field != '\0')    {	*ptr++ = *uname_field++;    }    return(header);}void get_system_info(si)struct system_info *si;{    struct tbl_loadavg labuf;    struct tbl_sysinfo sibuf;    struct tbl_swapinfo swbuf;    vm_statistics_data_t vmstats;    int swap_pages=0,swap_free=0,i;    long new_ticks[4],diff_ticks[4];    long delta_ticks;    if (do_last_pid)    {	/* last pid assigned */	(void) getkval(mpid_offset, &(si->last_pid), sizeof(si->last_pid), 		       "_mpid");    }    else    {	si->last_pid = -1;    }    /* get load averages */    if (table(TBL_LOADAVG,0,&labuf,1,sizeof(struct tbl_loadavg))<0) {	perror("TBL_LOADAVG");	return;    }    if (labuf.tl_lscale)   /* scaled */	for(i=0;i<3;i++) 	    si->load_avg[i] = ((double)labuf.tl_avenrun.l[i] /                                             (double)labuf.tl_lscale );    else                   /* not scaled */	for(i=0;i<3;i++) 	    si->load_avg[i] = labuf.tl_avenrun.d[i];    /* array of cpu state counters */    if (table(TBL_SYSINFO,0,&sibuf,1,sizeof(struct tbl_sysinfo))<0) {	perror("TBL_SYSINFO");	return;    }    new_ticks[0] = sibuf.si_user ; new_ticks[1] = sibuf.si_nice;    new_ticks[2] = sibuf.si_sys  ; new_ticks[3] = sibuf.si_idle;    delta_ticks=0;    for(i=0;i<4;i++) {	diff_ticks[i] = new_ticks[i] - old_cpu_ticks[i];	delta_ticks += diff_ticks[i];	old_cpu_ticks[i] = new_ticks[i];    }    si->cpustates = cpu_states;    if(delta_ticks)	for(i=0;i<4;i++) 	    si->cpustates[i] = (int)( ( (double)diff_ticks[i] /                                            (double)delta_ticks ) * 1000 );        /* memory information */    /* this is possibly bogus - we work out total # pages by */    /* adding up the free, active, inactive, wired down, and */    /* zero filled. Anyone who knows a better way, TELL ME!  */    /* Change: dont use zero filled. */    (void) vm_statistics(task_self(),&vmstats);    /* thanks DEC for the table() command. No thanks at all for   */    /* omitting the man page for it from OSF/1 1.2, and failing   */    /* to document SWAPINFO in the 1.3 man page. Lets hear it for */    /* include files. */    i=0;    while(table(TBL_SWAPINFO,i,&swbuf,1,sizeof(struct tbl_swapinfo))>0) {	swap_pages += swbuf.size;	swap_free  += swbuf.free;	i++;    }    memory_stats[0] = -1;    memory_stats[1] = pagetok(vmstats.active_count);    memory_stats[2] = pagetok((vmstats.free_count + vmstats.active_count +	vmstats.inactive_count + vmstats.wire_count));    memory_stats[3] = -1;    memory_stats[4] = pagetok((swap_pages - swap_free))/1024;    memory_stats[5] = pagetok(swap_pages)/1024;    memory_stats[6] = -1;    memory_stats[7] = pagetok(vmstats.free_count);    si->memory = memory_stats;}static struct handle handle;caddr_t get_process_info(si, sel, compare)struct system_info *si;struct process_select *sel;int (*compare)();{    register int i;    register int total_procs;    register int active_procs;    register struct osf1_top_proc **prefp;    register struct osf1_top_proc *pp;    struct tbl_procinfo p_i[8];    int j,k,r;    /* these are copied out of sel for speed */    int show_idle;    int show_uid;    int show_command;    /* 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_uid = sel->uid != -1;    show_command = sel->command != NULL;    /* count up process states and get pointers to interesting procs */    total_procs = 0;    active_procs = 0;    memset((char *)process_states, 0, sizeof(process_states));    prefp = pref;    pp=pbase;    for (j=0; j<nproc; j += 8)     {	r = table(TBL_PROCINFO, j, (struct tbl_procinfo *)p_i, 8,                                                sizeof(struct tbl_procinfo));	for (k=0; k < r; k++ , pp++) 	{	    if(p_i[k].pi_pid == 0) 	    {		pp->p_pid = 0;	    }	    else	    {		pp->p_pid = p_i[k].pi_pid;		pp->p_ruid = p_i[k].pi_ruid;		pp->p_flag = p_i[k].pi_flag;		pp->p_nice = getpriority(PRIO_PROCESS,p_i[k].pi_pid);		/* Load useful values into the proc structure */		do_threads_calculations(pp);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -