System Monitoring Program (MON)
Michael John Muuss <mike>
mike at brl-tgr.ARPA
Tue Dec 4 17:58:03 AEST 1984
echo 'sh - Makefile'
sed 's/^X//' <<'________This_Is_The_END________' >>Makefile
X
X# mon makefile
X#
X# Beware dependencies on mon.h are not properly stated.
X#
XOBJS = mon.o io.o vm.o netif.o display.o readnames.o
X
Xall: mon
X
Xmon: $(OBJS) mon.h
X cc -o mon $(OBJS) -lcurses -ltermlib
X
Xclean:
X rm -f core *.o mon a.out
X
Xprint:
X qpr mon.h mon.c io.c vm.c netif.c readnames.c display.c
________This_Is_The_END________
echo 'sh - display.c'
sed 's/^X//' <<'________This_Is_The_END________' >>display.c
X/*
X * D I S P L A Y . C
X *
X * This section handles the display initialization and updates for "mon"
X */
X#include "mon.h"
X#include <curses.h>
X
X#define HOSTLEN 40 /* Length of hostname */
X
X/* Screen Positions */
X#define LEFT 0
X#define PROCY 2
X#define CPUY 5
X#define TIMEY 8
X#define PAGEY 11
X#define CHARY 5
X#define CHARX 37
X#define NETIFY 17
X#define DISKY 2
X#define DISKX 55
X
X/*
X * DISPINIT - clears the screen, puts up the info labels, and
X * displays the initial information (device names).
X */
Xdispinit()
X{
X char hname[HOSTLEN];
X register int i;
X
X clear(); /* clear screen */
X gethostname(hname, HOSTLEN); /* host name in upper left */
X printw(hname);
X
X /* Put up the labels */
X mvprintw(PROCY,LEFT,"Procs: r d p s sl Mem: real ract virt vact free");
X mvprintw(DISKY,DISKX,"Disks: Kbps tps msps");
X mvprintw(CPUY,LEFT,"Cpu: ints scall csw");
X if (dualcpu)
X mvprintw(CPUY,LEFT+25,"Cpu2: csw");
X mvprintw(TIMEY,LEFT,"Time: user nice sys idle");
X if (dualcpu)
X mvprintw(TIMEY,LEFT+26,"Time2: user nice sys idle");
X mvprintw(PAGEY,LEFT,"Paging: re at pin pout oprs fr def sr");
X mvprintw(PAGEY+3,LEFT," nxf xf nzf zf nrf rf prf swi swo");
X mvprintw(CHARY,CHARX,"Char: in out");
X mvprintw(NETIFY,LEFT,"Name Ipkts Ierrs Opkts Oerrs Collis Oqueue");
X
X /* add the disk drive names to the screen */
X for(i = 0; i < DK_NDRIVE; i++) {
X if (*dr_name[i])
X mvprintw(DISKY+1+i,DISKX,dr_name[i]);
X else
X break;
X }
X mvprintw(DISKY+1+i,DISKX,"--------------------");
X mvprintw(DISKY+2+i,DISKX,"Total:");
X
X /* put up the network interface names */
X for (i = 0; i < numif; i++)
X mvprintw(NETIFY+1+i,LEFT,nifinfo[i].name);
X}
X
X/*
X * DISPUPDATE - updates the dynamic data on the screen.
X */
Xdispupdate()
X{
X int i;
X
X for (i = 0; i < numif; i++)
X mvprintw(NETIFY+1+i,LEFT+7,"%5d %5d %5d %5d %5d %5d",
X nifdat[i].ipackets, nifdat[i].ierrors,
X nifdat[i].opackets, nifdat[i].oerrors,
X nifdat[i].collisions, nifinfo[i].outqlen);
X}
________This_Is_The_END________
echo 'sh - io.c'
sed 's/^X//' <<'________This_Is_The_END________' >>io.c
X/*
X * I O
X *
X * Purpose: Read the kernel's I/O statistics and display selected
X * parameters about terminals and disks.
X *
X */
X
X#include "mon.h"
X
Xdouble kbps, tps; /* Kbytes/sec and xfers/sec */
Xint lasty; /* Last disk y location */
X
X/* Temporary Defines - All output should be moved to dispinfo */
X#include <curses.h>
X#define CHARX 37
X#define CHARY 5
X#define DISKX 55
X#define DISKY 2
X#define DISKOFF 6
X#define DISKWDS DISKOFF
X#define DISKXFER DISKOFF+4
X#define DISKSEEK DISKOFF+8
X
Xio()
X{
X int y;
X register i;
X long t;
X double tkbps, ttps; /* Totals for all drives */
X
X lseek(kmem, (long)namelist[X_DK_TIME].n_value, 0);
X read(kmem, s.dk_time, sizeof s.dk_time);
X lseek(kmem, (long)namelist[X_DK_XFER].n_value, 0);
X read(kmem, s.dk_xfer, sizeof s.dk_xfer);
X lseek(kmem, (long)namelist[X_DK_WDS].n_value, 0);
X read(kmem, s.dk_wds, sizeof s.dk_wds);
X lseek(kmem, (long)namelist[X_TK_NIN].n_value, 0);
X read(kmem, &s.tk_nin, sizeof s.tk_nin);
X lseek(kmem, (long)namelist[X_TK_NOUT].n_value, 0);
X read(kmem, &s.tk_nout, sizeof s.tk_nout);
X lseek(kmem, (long)namelist[X_DK_SEEK].n_value, 0);
X read(kmem, s.dk_seek, sizeof s.dk_seek);
X lseek(kmem, (long)namelist[X_DK_MSPW].n_value, 0);
X read(kmem, s.dk_mspw, sizeof s.dk_mspw);
X lseek(kmem, (long)namelist[X_HZ].n_value, 0);
X read(kmem, &hz, sizeof hz);
X for (i = 0; i < DK_NDRIVE; i++) {
X#define X(fld) t = s.fld[i]; s.fld[i] -= s1.fld[i]; s1.fld[i] = t
X X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time);
X }
X t = s.tk_nin; s.tk_nin -= s1.tk_nin; s1.tk_nin = t;
X t = s.tk_nout; s.tk_nout -= s1.tk_nout; s1.tk_nout = t;
X
X /* output character I/O counts */
X mvprintw(CHARY+1,CHARX+4,"%4.0f %5.0f", s.tk_nin/etime, s.tk_nout/etime);
X
X /* Display Drive statistics */
X tkbps = ttps = 0;
X for (i=0; i<DK_NDRIVE; i++) {
X if (stats(i)) {
X tkbps += kbps;
X ttps += tps;
X }
X }
X /* Display Totals */
X mvprintw(lasty+2, DISKX+DISKOFF, "%4.0f%4.0f", tkbps, ttps);
X}
X
X/*
X * Display statistics for dk drive number dn.
X * Returns 1 if totals should be updated.
X */
Xstats(dn)
X{
X int y;
X register i;
X double atime, words, xtime, itime;
X
X /* only display info for named (real) devices */
X if (!*dr_name[dn])
X return(0);
X
X y = dn + DISKY+1;
X lasty = y;
X if (s.dk_mspw[dn] == 0.0) {
X mvprintw(y,DISKX+DISKOFF,"%4.0f%4.0f%6.1f ", 0.0, 0.0, 0.0);
X return(0);
X }
X atime = s.dk_time[dn];
X atime /= (float) hz;
X words = s.dk_wds[dn]*32.0; /* number of 16 bit words transferred */
X xtime = s.dk_mspw[dn]*words; /* transfer time */
X itime = atime - xtime; /* time not transferring (seek time) */
X
X if (xtime < 0)
X itime += xtime, xtime = 0;
X if (itime < 0)
X xtime += itime, itime = 0;
X
X /* Avg Kbps, transfers/sec, avg seek time (in msec) */
X kbps = words/512/etime;
X tps = s.dk_xfer[dn]/etime;
X mvprintw(y,DISKX+DISKWDS,"%4.0f", kbps);
X mvprintw(y,DISKX+DISKXFER,"%4.0f", tps);
X mvprintw(y,DISKX+DISKSEEK,"%6.1f ",
X s.dk_seek[dn] ? itime*1000./s.dk_seek[dn] : 0.0);
X
X return(1); /* Update totals */
X}
X
X
________This_Is_The_END________
echo 'sh - mon.8b'
sed 's/^X//' <<'________This_Is_The_END________' >>mon.8b
X.TH MON 8 "26 April 1981"
X.de s1
X.if n .sp
X.if t .sp .1i
X..
X.de t1
X.if n .ta 5n
X.if t .ta 1i
X..
X.UC 4
X.SH NAME
Xmon \- display system activity
X.SH SYNOPSIS
X.B mon
X[ interval ]
X.SH DESCRIPTION
X.I Mon
Xprovides a screen oriented display of system activity.
XIt updates the display every second unless
X.I interval
Xis specified, then successive updates occur every
X.I interval
Xseconds.
X.PP
XThe format fields are:
X.PP
XTop Line: host name, load averages for 5 seconds, 1, 5, and 15 minutes,
Xand date.
X.PP
XProcs: information about numbers of processes in various states.
X.s1
X.t1
X.nf
Xr on run queue (does not include the running job, i.e. mon)
Xd waiting for "disk" i/o (sleeping with priority < PZERO)
Xp page wait
Xs runnable or short sleeper (< 20 secs) but swapped
Xsl sleeping in core.
X.fi
X.s1
XMem: information about the usage of virtual and real memory.
XVirtual pages are considered active if they belong to processes which
Xare running or have run in the last 20 seconds.
XA ``page'' here is 1024 bytes.
X.s1
X.t1
X.nf
Xreal total real pages used
Xract active real pages
Xvirt total virtual pages used
Xvact active virtual pages
Xfree size of the free list
X.fi
X.s1
XCpu: trap/interrupt rate averages per second
X.s1
X.t1
X.nf
Xints (non clock) device interrupts per second
Xscall system calls per second
Xcsw cpu context switch rate (switches/sec)
X.fi
X.s1
XTime: breakdown of percentage usage of CPU time
X.s1
X.nf
Xuser user time for normal and low priority processes
Xnice running "nice" jobs
Xsys system time
Xidle cpu idle
X.fi
X.s1
XPaging: information about page faults and paging activity.
XThese are averaged each second, and given in units per second.
X.s1
X.t1
X.nf
Xre page reclaims (simulating reference bits)
Xat pages attached (found in free list rather than swapdev
X or filsys)
Xpin pages paged in
Xpout pages paged out
Xoprs calls to paging routine
Xfr pages freed by daemon per second
Xdef anticipated short term memory shortfall
Xsr pages scanned by clock algorithm, per-second
Xnxf number of executable filled on demand (exfod) pages
X created
Xxf number of exfod's filled
Xnzf number of zero filled on demand (zfod) pages created
Xzf number of zfod's filled
Xnrf number of fill on demand pages mapped by vread (vrfod)
X created
Xrf number of vrfod's filled
Xprf pages reclaimed from free list
Xswi number of swapin operations
Xswo number of swapout operations
X.fi
X.s1
XChars: Number of chars from and to terminals during the interval.
X.fi
X.s1
XNetwork Interfaces: The name of the interface is given along with the
Xnumber of packets sent and received during the interval, the number of
Xinput and output errors, collisions (for ethernet type networks), and
Xthe output queue length.
X.fi
X.s1
XDisks: For each "alive" disk monitored.
X.s1
X.t1
X.nf
XKbps average Kbyte per second transfer rate during interval
Xtps transfers per second
Xmsps average milliseconds per seek during the interval
X.nf
X.s1
XCommands:
X ^L repaints the screen.
X q exits the program.
X Any other character will cause the screen to be updated (thus
X you can for example run "mon 100" and type single characters
X to take "snapshots" of the system).
X.s1
X.SH FILES
X/dev/kmem, /vmunix
X.SH SEE ALSO
XThe sections starting with ``Interpreting system activity'' in
X.IR "Installing and Operating 4.2bsd" .
X.SH AUTHOR
XPhillip Dykstra
________This_Is_The_END________
echo 'sh - mon.c'
sed 's/^X//' <<'________This_Is_The_END________' >>mon.c
X/*
X * M O N . C
X *
X * A program to moniter system activity.
X * Rework of earlier mon program. 17 Aug 84 - Phillip Dykstra
X *
X */
X
X#include "mon.h"
X#include <curses.h>
X#include <signal.h>
X
Xstruct sgttyb ttyb;
Xint done();
X
X/*
X * The namelist array. Uses to get the kernal variables needed
X * by all the MON routines. The order of this list MUST correspond
X * to the order of the definitions in mon.h
X */
Xstruct nlist namelist[] = {
X { "_dk_busy" },
X { "_dk_mspw" },
X { "_hz" },
X { "_cp_time" },
X { "_rate" },
X { "_total" },
X { "_deficit" },
X { "_dk_xfer" },
X { "_mbdinit" },
X { "_ubdinit" },
X { "_ifnet" },
X { "_dk_time" },
X { "_dk_wds" },
X { "_dk_seek" },
X { "_tk_nin" },
X { "_tk_nout" },
X { "_avenrun" },
X { "_cp2_time" }, /* 2nd CPU stats */
X { "_slavestart" }, /* Used to detect 2nd CPU */
X { 0 }
X};
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X register i;
X double f1, f2;
X extern char *ctime();
X
X/*
X * fill the namelist and open /dev/kmem
X */
X nlist("/vmunix", namelist);
X if(namelist[X_DK_BUSY].n_type == 0) {
X printf("dk_busy not found in /vmunix namelist\n");
X exit(1);
X }
X kmem = open("/dev/kmem", 0);
X if(kmem < 0) {
X printf("cannot open /dev/kmem\n");
X exit(1);
X }
X if(argc > 1)
X intv = (atoi(argv[1]));
X else intv = 1;
X
X/*
X * do all things that need to be done only once
X */
X lseek(kmem, (long)namelist[X_DK_MSPW].n_value, 0);
X read(kmem, s.dk_mspw, sizeof s.dk_mspw);
X lseek(kmem, (long)namelist[X_HZ].n_value, 0);
X read(kmem, &hz, sizeof hz);
X read_names();
X dualcpu = 0;
X if (namelist[X_SLAVESTART].n_type)
X dualcpu++;
X/*
X * monitor parameters forever
X */
X worker();
X /* NOTREACHED */
X}
X
Xchar obuf[BUFSIZ]; /* Output buffer */
X
Xworker()
X{
X long clock;
X struct timeval tintv;
X int i, tin;
X
X /* set up signals */
X signal(SIGINT, done);
X signal(SIGQUIT, done);
X
X /* set CBREAK mode with no buffering on stdin */
X setbuf(stdin, 0);
X setbuf(stdout, obuf);
X ioctl(0, TIOCGETP, &ttyb);
X ttyb.sg_flags |= CBREAK;
X ioctl(fileno(stdin), TIOCSETP, (char *)&ttyb);
X
X tintv.tv_sec = intv;
X tintv.tv_usec = 0;
X initscr(); /* init curses package */
X nifinit(); /* get initial net interfaces data */
X dispinit(); /* initialize display */
X for(;;){
X vm();
X io();
X nifupdate();
X /* get load average */
X lseek(kmem, (long)namelist[LOADAV].n_value, 0);
X read(kmem, &loadavg[0], sizeof loadavg);
X mvprintw(0,13,"%4.2f %4.2f %4.2f %4.2f", loadavg[3], loadavg[0], loadavg[1], loadavg[2]);
X time(&clock);
X mvprintw(0,40,ctime(&clock));
X dispupdate();
X mvprintw(23, 0, "CMD> ");
X refresh();
X tin = 1;
X i = select(2, &tin, (int *)0, (int *)0, &tintv);
X if (i && tin) {
X i = getchar();
X if (i == 12)
X dispinit();
X else if (i == 'q')
X done();
X }
X }
X}
X
X/*
X * DONE - put the term back in non CBREAK mode and exit.
X */
Xdone()
X{
X ioctl(0, TIOCGETP, &ttyb);
X ttyb.sg_flags &= ~CBREAK;
X ioctl(fileno(stdin), TIOCSETP, (char *)&ttyb);
X mvprintw(23,0,"\n");
X refresh();
X exit(1);
X}
________This_Is_The_END________
echo 'sh - mon.h'
sed 's/^X//' <<'________This_Is_The_END________' >>mon.h
X/*
X * M O N . H
X *
X * Contains all includes and global defines/data needed by "mon"
X */
X#include <stdio.h>
X#include <ctype.h>
X#include <nlist.h>
X#include <sys/types.h>
X#include <sys/vm.h> /* virtual memory info struct */
X#include <sys/dk.h> /* disk info struct */
X#include <sys/time.h>
X
X/*
X * The main namelist entries. This order MUST correspond to the
X * definition of namelist in main.
X */
X#define X_DK_BUSY 0
X#define X_DK_MSPW 1
X#define X_HZ 2
X#define X_CP_TIME 3
X#define X_RATE 4
X#define X_TOTAL 5
X#define X_DEFICIT 6
X#define X_DK_XFER 7
X#define X_MBDINIT 8
X#define X_UBDINIT 9
X#define N_IFNET 10
X#define X_DK_TIME 11
X#define X_DK_WDS 12
X#define X_DK_SEEK 13
X#define X_TK_NIN 14
X#define X_TK_NOUT 15
X#define LOADAV 16
X#define X_CP_TIME2 17 /* 2nd CPU stats */
X#define X_SLAVESTART 18 /* 2nd cpu existance test */
X
Xextern struct nlist namelist[];
Xint intv; /* interval time */
Xint numif; /* number of interfaces */
Xint dualcpu; /* flag to indicate dual CPU */
Xint kmem, hz;
Xint deficit;
Xdouble etime;
Xdouble loadavg[4];
X
X/* drive names and numbers */
Xchar dr_name[DK_NDRIVE][10];
Xchar dr_unit[DK_NDRIVE];
X
X/*
X * Net Interfaces Data - consists of two structures:
X *
X * nifinfo contains the "static" data (names, addresses)
X * and iterative data which does not consist
X * of "running totals".
X *
X * nifdata The "dynamic" running total data. Two copies,
X * a "total" and "interval" are kept.
X *
X */
X#define MAXIF 10 /* ten interfaces maximum */
X
Xstruct nifinfo {
X char name[16]; /* interface name */
X int outqlen; /* output queue length */
X /* add address, netname, etc. eventually */
X /* also non totaling data */
X} nifinfo[MAXIF];
X
Xstruct nifdata {
X int ipackets; /* input packets */
X int ierrors; /* input errors */
X int opackets; /* output packets */
X int oerrors; /* output errors */
X int collisions;
X} nifdat[MAXIF], niftot[MAXIF];
X
X/* state info */
Xstruct state {
X long cp_time[CPUSTATES];
X long cp_time2[CPUSTATES]; /* 2nd CPU */
X long dk_time[DK_NDRIVE];
X long dk_wds[DK_NDRIVE];
X long dk_seek[DK_NDRIVE];
X long dk_xfer[DK_NDRIVE];
X float dk_mspw[DK_NDRIVE];
X long tk_nin;
X long tk_nout;
X struct vmmeter Rate;
X struct vmtotal Total;
X} s, s1;
X
X#define rate s.Rate
X#define total s.Total
________This_Is_The_END________
echo 'sh - netif.c'
sed 's/^X//' <<'________This_Is_The_END________' >>netif.c
X/*
X * N E T I F . C
X *
X * This section of mon handles the network interfaces.
X *
X * nifinit() initializes "static" info on interfaces.
X * nifupdate() gets "dynamic" info on net interfaces.
X */
X#include "mon.h"
X#include <sys/socket.h>
X#include <net/if.h>
X#include <netinet/in.h>
X
Xchar *index();
X
X/*
X * NIFINIT - initialize the static network interfaces info such
X * as device names, addresses, etc. Also calls nifupdate() once
X * to set up initial values for data with running totals.
X */
Xnifinit()
X{
X off_t firstifnet; /* offset to first ifnet struct */
X off_t ifnetp; /* points to ifnet struct in kmem */
X struct ifnet ifnet;
X struct nifinfo *nifip;
X
X /* check for valid kernal offset */
X if (namelist[N_IFNET].n_type == NULL) {
X fprintf(stderr, "mon: ifnet symbol not defined!\n");
X return;
X }
X
X /* get starting address of ifnet structure chain */
X lseek(kmem, namelist[N_IFNET].n_value, 0);
X read(kmem, &firstifnet, sizeof(firstifnet));
X
X /* get info for each interface in chain */
X numif = 0; /* count number of interfaces */
X ifnetp = firstifnet;
X nifip = &nifinfo[0];
X while (ifnetp) {
X char *cp;
X
X numif++;
X /* get an ifnet entry */
X lseek(kmem, (long)ifnetp, 0);
X read(kmem, &ifnet, sizeof(ifnet));
X
X /* build its interface name */
X lseek(kmem, (long)ifnet.if_name, 0);
X read(kmem, nifip->name, 15);
X nifip->name[15] = '\0';
X cp = index(nifip->name, '\0');
X sprintf(cp, "%d", ifnet.if_unit);
X
X /* other info comes here */
X
X if (++nifip >= &nifinfo[MAXIF])
X break; /* no more room for interfaces */
X
X ifnetp = (off_t)ifnet.if_next; /* link to next ifnet struct */
X }
X
X nifupdate(); /* init running totals */
X}
X
X/*
X * NIFUPDATE - gets the "dynamic" info about the network interfaces.
X */
Xnifupdate()
X{
X off_t ifnetp; /* pointer to ifnet struct in kmem */
X struct ifnet ifnet;
X int i;
X
X if (namelist[N_IFNET].n_type == NULL)
X return; /* no net interfaces */
X
X /* get info from ifnet struct chain */
X lseek(kmem, namelist[N_IFNET].n_value, 0);
X read(kmem, &ifnetp, sizeof(ifnetp));
X i = 0;
X while (ifnetp) {
X lseek(kmem, (long)ifnetp, 0);
X read (kmem, &ifnet, sizeof(ifnet));
X
X /* extract interval data from ifnet and update totals */
X nifdat[i].ipackets = ifnet.if_ipackets - niftot[i].ipackets;
X niftot[i].ipackets = ifnet.if_ipackets;
X nifdat[i].ierrors = ifnet.if_ierrors - niftot[i].ierrors;
X niftot[i].ierrors = ifnet.if_ierrors;
X nifdat[i].opackets = ifnet.if_opackets - niftot[i].opackets;
X niftot[i].opackets = ifnet.if_opackets;
X nifdat[i].oerrors = ifnet.if_oerrors - niftot[i].oerrors;
X niftot[i].oerrors = ifnet.if_oerrors;
X nifdat[i].collisions = ifnet.if_collisions - niftot[i].collisions;
X niftot[i].collisions = ifnet.if_collisions;
X /* extract nifinfo (other stuff) data from ifnet */
X /* OTHER STUFF OF INTEREST HERE */
X nifinfo[i].outqlen = ifnet.if_snd.ifq_len;
X
X if (++i >= MAXIF)
X break; /* no more room for interfaces */
X
X ifnetp = (off_t)ifnet.if_next; /* link to next ifnet struct */
X }
X}
________This_Is_The_END________
echo 'sh - readnames.c'
sed 's/^X//' <<'________This_Is_The_END________' >>readnames.c
X/*
X * R E A D N A M E S
X *
X * purpose: Reads the names of the disks from kernel space
X *
X */
X#include "mon.h"
X#include <sys/buf.h> /* needed by following two includes */
X#include <vaxuba/ubavar.h> /* unibus adapters */
X#include <vaxmba/mbavar.h> /* massbus adapters */
X
X#define steal(where, var) lseek(kmem, where, 0); read(kmem, &var, sizeof var);
X
Xread_names()
X{
X struct mba_device mdev;
X register struct mba_device *mp;
X struct mba_driver mdrv;
X short two_char;
X char *cp = (char *) &two_char;
X struct uba_device udev, *up;
X struct uba_driver udrv;
X
X mp = (struct mba_device *) namelist[X_MBDINIT].n_value;
X up = (struct uba_device *) namelist[X_UBDINIT].n_value;
X if (mp) for (;;) {
X steal(mp++, mdev);
X if (mdev.mi_driver == 0)
X break;
X if (mdev.mi_dk < 0 || mdev.mi_alive == 0)
X continue;
X steal(mdev.mi_driver, mdrv);
X steal(mdrv.md_dname, two_char);
X sprintf(dr_name[mdev.mi_dk], "%c%c%d", cp[0], cp[1], mdev.mi_unit);
X dr_unit[mdev.mi_dk] = mdev.mi_unit;
X }
X if (up) for (;;) {
X steal(up++, udev);
X if (udev.ui_driver == 0)
X break;
X if (udev.ui_dk < 0 || udev.ui_alive == 0)
X continue;
X steal(udev.ui_driver, udrv);
X steal(udrv.ud_dname, two_char);
X sprintf(dr_name[udev.ui_dk], "%c%c%d", cp[0], cp[1], udev.ui_unit);
X dr_unit[udev.ui_dk] = udev.ui_unit;
X }
X}
________This_Is_The_END________
echo 'sh - vm.c'
sed 's/^X//' <<'________This_Is_The_END________' >>vm.c
X/*
X * V M
X *
X * Purpose: Read the system virtual memory status info from kernel
X * space and write it onto the virtual screen used by curses(3).
X *
X * Bugs: This routime (like the others) it does its own
X * printing. This makes it very difficult to change the screen
X * format. A better solution would be to move all the prints
X * into a screen update function.
X */
X
X#include "mon.h"
X#include <machine/param.h> /* defines bytes/page */
X
X/* Temporary defines */
X#define PROCS 2
X#define CPUY 5
X#define TIMEY 8
X#define PAGE 11
X
Xvm()
X{
X register i,j;
X long t; /* temporary */
X
X lseek(kmem, (long)namelist[X_CP_TIME].n_value, 0);
X read(kmem, s.cp_time, sizeof s.cp_time);
X /* Check for 2nd CPU stats */
X if (dualcpu) {
X lseek(kmem, (long)namelist[X_CP_TIME2].n_value, 0);
X read(kmem, s.cp_time2, sizeof s.cp_time2);
X }
X lseek(kmem, (long)namelist[X_DK_XFER].n_value, 0);
X read(kmem, s.dk_xfer, sizeof s.dk_xfer);
X lseek(kmem, (long)namelist[X_RATE].n_value, 0);
X read(kmem, &rate, sizeof rate);
X lseek(kmem, (long)namelist[X_TOTAL].n_value, 0);
X read(kmem, &total, sizeof total);
X lseek(kmem, (long)namelist[X_DEFICIT].n_value, 0);
X read(kmem, &deficit, sizeof deficit);
X etime = 0;
X for (i=0; i < CPUSTATES; i++) {
X t = s.cp_time[i];
X s.cp_time[i] -= s1.cp_time[i];
X s1.cp_time[i] = t;
X if (dualcpu) {
X t = s.cp_time2[i];
X s.cp_time2[i] -= s1.cp_time2[i];
X s1.cp_time2[i] = t;
X }
X etime += s.cp_time[i]; /* interval must count 1 CPU only */
X }
X if(etime == 0.)
X etime = 1.;
X etime /= (float) hz;
X
X /* Display the procs line */
X mvprintw(PROCS+1,6,"%2d%2d%2d%2d %2d", total.t_rq, total.t_dw, total.t_pw, total.t_sw, total.t_sl);
X#define pgtok(a) ((a)*NBPG/1024)
X mvprintw(PROCS+1,23,"%5d %5d", pgtok(total.t_rm), pgtok(total.t_arm) );
X mvprintw(PROCS+1,34,"%6d %5d", pgtok(total.t_vm), pgtok(total.t_avm) );
X mvprintw(PROCS+1,47,"%5d", pgtok(total.t_free));
X
X /* Display paging info */
X mvprintw(PAGE+1,6,"%4d %3d",
X (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec)),
X (rate.v_xsfrec+rate.v_xifrec));
X mvprintw(PAGE+1,14,"%4d %4d", pgtok(rate.v_pgpgin),
X pgtok(rate.v_pgpgout));
X /* operations per time is (pgin + pgout) */
X mvprintw(PAGE+1,24,"%4d", (pgtok(rate.v_pgin)+
X pgtok(rate.v_pgout)));
X mvprintw(PAGE+1,29,"%4d %4d %4d", pgtok(rate.v_dfree)
X , pgtok(deficit), rate.v_scan);
X
X /* Display CPU info */
X mvprintw(CPUY+1,4,"%4d %4d", (rate.v_intr) - hz, rate.v_syscall);
X mvprintw(CPUY+1,17,"%4d", rate.v_swtch);
X if (dualcpu)
X mvprintw(CPUY+1,30,"%4d", rate.v_swtch2);
X cputime();
X
X /* Display additional stuff */
X mvprintw(PAGE+4,6,"%4d%4d %4d%4d %4d%4d %4d %4d%4d",
X rate.v_nexfod, rate.v_exfod,
X rate.v_nzfod, rate.v_zfod,
X rate.v_nvrfod, rate.v_vrfod,
X rate.v_pgfrec,
X rate.v_swpin, rate.v_swpout);
X}
X
X
X/*
X * Display cpu time info (%time in each state)
X */
Xcputime()
X{
X int x;
X double t, t2;
X register i;
X
X t = t2 = 0;
X for(i=0; i<CPUSTATES; i++) {
X t += s.cp_time[i];
X t2 += s.cp_time2[i];
X }
X if(t == 0.)
X t = 1.;
X if (t2 == 0.)
X t2 = 1.;
X x = 6;
X for(i=0; i<CPUSTATES; i++){
X mvprintw(TIMEY+1,x,"%3.0f", 100 * s.cp_time[i]/t);
X if (dualcpu)
X mvprintw(TIMEY+1,x+27,"%3.0f", 100 * s.cp_time2[i]/t2);
X x += 5;
X }
X}
________This_Is_The_END________
More information about the Comp.sources.unix
mailing list