home *** CD-ROM | disk | FTP | other *** search
- static char sccsid[] = "@(#)$Id: mapmem.c, V1.1.1.2 88/11/28 18:16:45 $";
-
- /*
- * map.c - display kernel allocation map information
- * Version : 1.1.1.2 - 88/11/28 18:16:45
- * Author : Michael J. Young
- * USmail : Software Development Technologies, Inc.
- * 375 Dutton Rd
- * Sudbury MA 01776
- * UUCP : harvard!sdti!mjy
- * Internet : mjy@sdti.SDTI.COM
- *
- * =========================================================================
- * Copyright (C) 1988, Michael J. Young.
- * Permission is hereby granted to copy and distribute this program for
- * non-commercial purposes, provided that this notice is not removed.
- *
- * This program is being provided "as is", with no warrantee as to safety or
- * accuracy of results.
- *
- * Please send bug reports and enhancements to me at the above address.
- * =========================================================================
- */
-
- /*
- * Modification History:
- *
- * Wed Nov 23 09:39:01 EST 1988 - M. Young (mjy@sdti.SDTI.COM),
- * Originated.
- */
-
- #define patch_level 0
-
- #include <nlist.h>
- #include <stdio.h>
- #include <sys/map.h>
- #include <sys/param.h>
- #include <fcntl.h>
- #include <curses.h>
- #include <sys/types.h>
- #include <time.h>
- #include <varargs.h>
- #include <signal.h>
-
- /*
- * sizes of the two major allocation maps maintained by the kernel. These
- * values are actually contained in the linkkit config.h. If that file is
- * not available, they must be set here.
- */
- #ifdef SMAPSIZ
- # define SMAPSIZE SMAPSIZ
- #else
- # define SMAPSIZE 75
- #endif
-
- #ifdef CMAPSIZ
- # define CMAPSIZE CMAPSIZ
- #else
- # define CMAPSIZE 150
- #endif
-
- /*
- * The following definitions specify the dimensions of the display map.
- * Change to suit your tastes.
- */
- #define MAX_ROWS 20
- #define MAX_COLUMNS 64
- #define MAX_ENTRIES (MAX_ROWS*MAX_COLUMNS)
-
- /*
- * the following defines are used to index the namelist array. Their
- * definitions must be consistent with the order of the namelist array.
- */
- #define CORE_MAP 0
- #define SWAP_MAP 1
- #define MAX_MEM 2
- #define N_SWAP 3
- #define PHYS_MEM 4
-
- /*
- * namelist array : contains a list of names to be extracted from the kernel
- * image using the nlist function.
- */
- struct nlist namelist[] = {
- { "coremap", 0, 0, 0, 0, 0 },
- { "swapmap", 0, 0, 0, 0, 0 },
- { "maxmem", 0, 0, 0, 0, 0 },
- { "nswap", 0, 0, 0, 0, 0 },
- { "physmem", 0, 0, 0, 0, 0 },
- { "", 0, 0, 0, 0, 0 }
- };
-
- struct map smapbf[SMAPSIZE]; /* local copy of swap allocation map */
- struct map cmapbf[CMAPSIZE]; /* local copy of core allocation map */
- int kmaxmem = 0; /* local copy of maxmem */
- int kphysmem = 0; /* local copy of physmem */
- int knswap = 0; /* local copy of nswap */
-
- int kmem = 0; /* file handle for kernel memory */
- int delay = 1; /* seconds between screen updates */
-
- char dmap[MAX_ENTRIES] = 0; /* display map */
-
- int swap_scale = 1; /* scale factor for swap map display */
- int core_scale = 1; /* scale factor for core map display */
-
- /*
- * various useful definitions
- */
- typedef int boolean;
-
- /*#define FALSE 0 /* defined in curses.h */
- /*#define TRUE 1 /* defined in curses.h */
-
- /*
- * various function declarations
- */
- extern long lseek();
- extern int read();
- extern time_t time();
-
- /*
- * interface to system error messages
- */
- char *prog_name = NULL;
-
- extern char *sys_errlist[];
- extern int sys_nerr;
- extern int errno;
-
- /*
- * error : performs a function similar to perror(3), but supports variable
- * argument lists. Prints out a formatted error string to stderr, followed if
- * possible by an appropriate system error message. Control is then
- * returned to the system with an error status. This function does not
- * return.
- */
- /* VARARGS0 */
- void error (va_alist)
- va_dcl /* varargs */
- {
- int err; /* 1st arg - error number */
- char *str; /* 2nd arg - error format string */
- va_list args;
- va_start(args);
- err = va_arg (args, int);
- str = va_arg (args, char *);
- fprintf (stderr, "%s: ", prog_name);
- vfprintf (stderr, str, args);
- if (err != 0){
- if (err <= sys_nerr && err > 0)
- fprintf (stderr, " : %s\n", sys_errlist[err]);
- else
- fprintf (stderr, " : unknown error : %d\n", err);
- }
- va_end(args);
- endwin();
- exit(1);
- }
-
- void version (){
- printf ("\nKernel Allocation Map Display\n");
- printf ("Version : 1.1 - 88/11/28 18:16:45, Patch Level %d\n", patch_level);
- }
-
- void usage(){
- version();
- printf ("Usage : map [-[?h]] [-d#]\n\n");
- printf ("\t-d#\tDelay '#' seconds between screen updates. Defaults\n");
- printf ("\t\tto 1 second.\n");
- printf ("\t-h\tDisplays this message.\n");
- printf ("\t-v\tDisplays version and patch level of program.\n");
- printf ("\t-?\tDisplays this message.\n");
- }
-
- /*
- * get_nlist : fetches the required namelist from the kernel image
- */
- void get_nlist(){
- if (nlist ("/unix", namelist) != 0){
- error (errno, "could not get namelist");
- }
- }
-
- /*
- * open_kmem : opens kernel memory
- */
- void open_kmem(){
-
- /*
- * open kernel memory
- */
- if ((kmem=open ("/dev/kmem", O_RDONLY)) == -1){
- error (errno, "could not open /dev/kmem");
- }
- }
-
- /*
- * init_kmem : reads kernel memory to initialize various static values
- * that are important for future processing.
- */
- void init_kmem (){
- /*
- * fetch maxmem (maximum free memory available to a process)
- */
- if (lseek (kmem, namelist[MAX_MEM].n_value, 0) != namelist[MAX_MEM].n_value){
- error (errno, "could not seek maxmem");
- }
- if (read (kmem, &kmaxmem, sizeof (int)) != sizeof (int)){
- error (errno, "could not read maxmem");
- }
-
- /*
- * fetch physmem (maximum physical memory present in the system)
- */
- if (lseek (kmem, namelist[PHYS_MEM].n_value, 0) != namelist[PHYS_MEM].n_value){
- error (errno, "could not seek physmem");
- }
- if (read (kmem, &kphysmem, sizeof (int)) != sizeof (int)){
- error (errno, "could not read physmem");
- }
-
- /*
- * fetch nswap (total blocks in the swap device)
- */
- if (lseek (kmem, namelist[N_SWAP].n_value, 0) != namelist[N_SWAP].n_value){
- error (errno, "could not seek nswap");
- }
- if (read (kmem, &knswap, sizeof (int)) != sizeof (int)){
- error (errno, "could not read nswap");
- }
-
- /*
- * calculate the scale factor for the display maps. The scale
- * factors should be set in such a way that a single screen can
- * display the entire map. The scale factors are then massaged to
- * ensure that they are always even. This is done in multiple
- * statements to ensure that smart compilers don't optimize the
- * multiplies and divides away. I'm sure there's a more elegant
- * and reliable way, but this seems to work.
- */
- swap_scale = (knswap + MAX_ENTRIES - 1) / MAX_ENTRIES;
- swap_scale = (swap_scale + 1) / 2;
- swap_scale *= 2;
- core_scale = (kphysmem + MAX_ENTRIES - 1) / MAX_ENTRIES;
- core_scale = (core_scale + 1) / 2;
- core_scale *= 2;
- }
-
- /*
- * read_map : copies the specified kernel allocation map into local memory
- * for future processing.
- */
- void read_map(loc, buf, size)
- daddr_t loc; /* location in kernel to be read */
- struct map *buf; /* buffer in which to place copy */
- unsigned size; /* number of map entries to read */
- {
- if (lseek (kmem, loc, 0) != loc){
- error (errno, "could not seek kernel map");
- }
- if (read (kmem, buf, size*sizeof (struct map)) != size*sizeof (struct map)){
- error (errno, "could not read kernel map");
- }
- }
-
- /*
- * update_map : modifies all of the appropriate display map cells according
- * that are affected by the specified kernel allocation map item.
- */
- void update_map (dmap, mp, scale)
- char dmap[];
- struct map *mp;
- int scale;
- {
- int entry;
- int map_index;
- int size;
- size = mp->m_size;
- for (entry = mp->m_addr; size; entry++){
- map_index = entry / scale;
- dmap[map_index] = 0;
- size--;
- }
- }
-
- /*
- * interpret_map : scans through the copy of the kernel allocation map and
- * updates the specified display map accordingly. The total number of free
- * blocks in the map are returned.
- */
- int interpret_map(dmap, kmp, scale)
- char dmap[];
- struct map *kmp;
- int scale;
- {
- int total_free = 0;
- struct map *mp;
- memset (dmap, 1, MAX_ENTRIES);
- for (mp = kmp; mp->m_size; mp++){
- total_free += mp->m_size;
- update_map (dmap, mp, scale);
- }
- return total_free;
- }
-
- /*
- * print_map : scans the allocation map, displaying it in the standard
- * window. Allocated cells are marked with an asterisk ('*'), and free
- * cells are marked with a period ('.').
- */
- void print_map(dmap, scale, total_size)
- char dmap[];
- int scale;
- long total_size;
- {
- int i, j, k;
- int entry;
- move (2,0);
- for (i = 0; i < MAX_ROWS; i++){
- k = i*MAX_COLUMNS;
- if (((long)k*scale) >= total_size)break;
- printw ("%08lx: ", (long)k * scale);
- for (j = 0; j < MAX_COLUMNS; j++){
- if ((((long)k+j)*scale) >= total_size)break;
- entry = (i*MAX_COLUMNS+j);
- if (dmap[entry] != 0)addch ('*');
- else addch ('.');
- }
- addch ('\n');
- }
- }
-
- void interrupt (sig)
- int sig;
- {
- move (0,0);
- clrtobot();
- refresh();
- endwin();
- exit(0);
- }
-
- /*
- * init : performs system and curses initialization
- */
- void init (argc, argv)
- int argc;
- char *argv[];
- {
- int i;
- boolean done;
- char *cp;
-
- /*
- * before we go any further, disable interrupts
- */
- signal (SIGINT, SIG_IGN);
- signal (SIGQUIT, SIG_IGN);
- signal (SIGHUP, SIG_IGN);
- signal (SIGTERM, SIG_IGN);
-
- /*
- * save program name for future reference
- */
- prog_name = argv[0];
-
- for (i = 1; i < argc; i++){
- cp = argv[i];
- if (*cp == '-'){
- done = FALSE;
- while (*++cp && !done){
- switch (*cp){
-
- case 'd': /* delay */
- if (cp[1]){
- delay = atoi (++cp);
- done = TRUE;
- }
- else {
- delay = atoi (argv[++i]);
- }
- break;
-
- case 'v': /* display version */
- version();
- exit(0);
-
- case '?': /* usage */
- case 'h':
- usage();
- exit(0);
-
- default:
- fprintf (stderr, "illegal option : %c; ignored.\n", *cp);
- break;
- }
- }
- }
- }
-
- /*
- * curses initialization
- */
- initscr();
- cbreak();
- noecho();
- nodelay (stdscr, 1);
-
- /*
- * print out a simple command menu
- */
- mvaddch (23, 0, '[');
- attrset (A_BOLD);
- addch ('m');
- attroff (A_BOLD);
- addch (',');
- attrset (A_BOLD);
- addch ('c');
- attroff (A_BOLD);
- addstr ("]=memory allocation map [");
- attrset (A_BOLD);
- addch ('s');
- attroff (A_BOLD);
- addstr ("]=swap allocation map [");
- attrset (A_BOLD);
- addch ('q');
- attroff (A_BOLD);
- addch (',');
- attrset (A_BOLD);
- addch ('x');
- attroff (A_BOLD);
- addch (',');
- attrset (A_BOLD);
- addch ('e');
- attrset (A_NORMAL);
- addstr ("]=exit");
-
- /*
- * now that curses is initialized, catch the interrupt signal
- * so we can die gracefully
- */
- signal (SIGINT, interrupt);
- signal (SIGQUIT, interrupt);
- signal (SIGHUP, interrupt);
- signal (SIGTERM, interrupt);
-
- /*
- * get ready to access kernel memory
- */
- open_kmem();
- get_nlist ();
- init_kmem();
- }
-
- int main (argc, argv)
- int argc;
- char *argv[];
- {
- struct tm *tmbuf; /* to hold current time */
- time_t tm;
- boolean done = FALSE; /* will be nonzero when ready to quit */
- int mem_or_swap = 0; /* 0 = display core map, 1 = swap map */
- int free = 0; /* free items in allocation map */
-
- init (argc, argv);
- while (!done){
-
- /*
- * get and display current time
- */
- time (&tm);
- tmbuf = localtime (&tm);
- move (0,0);
- clrtoeol();
- mvprintw (0, 67, "%02d:%02d:%02d", tmbuf->tm_hour, tmbuf->tm_min, tmbuf->tm_sec);
-
- if (mem_or_swap == 0){
-
- /*
- * update and display core map
- */
- read_map (namelist[CORE_MAP].n_value, cmapbf, CMAPSIZE);
- free = interpret_map (dmap, cmapbf, core_scale);
- standout();
- mvaddstr (0, 31, "Memory Allocation");
- standend();
- move (1,0);
- clrtoeol();
- mvprintw (1, 0, "Total Memory = %ld KBytes, %ld Kernel, %ld Free",
- ((long)kphysmem*NBPC)/1024,
- ((long)(kphysmem-kmaxmem)*NBPC)/1024,
- ((long)free*NBPC)/1024);
- mvprintw (1, 58, "Scale Factor = %2d", core_scale);
- print_map (dmap, core_scale*NBPC, (long)kphysmem*NBPC);
- }
- else {
-
- /*
- * update and display swap map
- */
- read_map (namelist[SWAP_MAP].n_value, smapbf, SMAPSIZE);
- free = interpret_map (dmap, smapbf, swap_scale);
- standout();
- mvaddstr (0, 29, "Swap Device Allocation");
- standend();
- move (1,0);
- clrtoeol();
- mvprintw (1, 0, "Total swap space = %d Blocks, %d Free", knswap, free);
- mvprintw (1, 58, "Scale Factor = % d", swap_scale);
- print_map (dmap, swap_scale, (long)knswap);
- }
-
- /*
- * refresh the screen and wait a while
- */
- refresh();
- sleep (delay);
-
- /*
- * look for any new commands
- */
- switch (getch()){
- case 'c': /* switch to core (memory) map */
- case 'm':
- mem_or_swap = 0;
- break;
-
- case 's': /* switch to swap map */
- mem_or_swap = 1;
- break;
-
- case 'q': /* quit */
- case 'e':
- case 'x':
- done = TRUE;
- break;
-
- default: /* illegal command, ignore it */
- break;
- }
-
- }
- move (0,0);
- clrtobot();
- refresh();
- endwin();
- }
-
-