home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume5 / mapmem / mapmem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-03  |  12.6 KB  |  550 lines

  1. static char sccsid[] = "@(#)$Id: mapmem.c, V1.1.1.2 88/11/28 18:16:45 $";
  2.  
  3. /*
  4.  * map.c - display kernel allocation map information
  5.  * Version : 1.1.1.2 - 88/11/28 18:16:45
  6.  * Author   : Michael J. Young
  7.  * USmail   : Software Development Technologies, Inc.
  8.  *            375 Dutton Rd
  9.  *            Sudbury MA 01776
  10.  * UUCP     : harvard!sdti!mjy
  11.  * Internet : mjy@sdti.SDTI.COM
  12.  *
  13.  * =========================================================================
  14.  * Copyright (C) 1988, Michael J. Young.
  15.  * Permission is hereby granted to copy and distribute this program for
  16.  * non-commercial purposes, provided that this notice is not removed.
  17.  *
  18.  * This program is being provided "as is", with no warrantee as to safety or
  19.  * accuracy of results.
  20.  *
  21.  * Please send bug reports and enhancements to me at the above address.
  22.  * =========================================================================
  23.  */
  24.  
  25. /*
  26.  * Modification History:
  27.  *
  28.  * Wed Nov 23 09:39:01 EST 1988 - M. Young (mjy@sdti.SDTI.COM),
  29.  *    Originated.
  30.  */
  31.  
  32. #define patch_level 0
  33.  
  34. #include <nlist.h>
  35. #include <stdio.h>
  36. #include <sys/map.h>
  37. #include <sys/param.h>
  38. #include <fcntl.h>
  39. #include <curses.h>
  40. #include <sys/types.h>
  41. #include <time.h>
  42. #include <varargs.h>
  43. #include <signal.h>
  44.  
  45. /*
  46.  * sizes of the two major allocation maps maintained by the kernel.  These
  47.  * values are actually contained in the linkkit config.h.  If that file is
  48.  * not available, they must be set here.
  49.  */
  50. #ifdef    SMAPSIZ
  51. # define SMAPSIZE    SMAPSIZ
  52. #else
  53. # define SMAPSIZE  75
  54. #endif
  55.  
  56. #ifdef    CMAPSIZ
  57. # define CMAPSIZE    CMAPSIZ
  58. #else
  59. # define    CMAPSIZE 150
  60. #endif
  61.  
  62. /*
  63.  * The following definitions specify the dimensions of the display map.
  64.  * Change to suit your tastes.
  65.  */
  66. #define    MAX_ROWS    20
  67. #define    MAX_COLUMNS    64
  68. #define MAX_ENTRIES    (MAX_ROWS*MAX_COLUMNS)
  69.  
  70. /*
  71.  * the following defines are used to index the namelist array.  Their
  72.  * definitions must be consistent with the order of the namelist array.
  73.  */
  74. #define CORE_MAP    0
  75. #define    SWAP_MAP     1
  76. #define MAX_MEM     2
  77. #define    N_SWAP         3
  78. #define    PHYS_MEM    4
  79.  
  80. /*
  81.  * namelist array : contains a list of names to be extracted from the kernel
  82.  * image using the nlist function.
  83.  */
  84. struct nlist namelist[] = {
  85.     { "coremap", 0, 0, 0, 0, 0 },
  86.     { "swapmap", 0, 0, 0, 0, 0 },
  87.     { "maxmem",  0, 0, 0, 0, 0 },
  88.     { "nswap",   0, 0, 0, 0, 0 },
  89.     { "physmem", 0, 0, 0, 0, 0 },
  90.     { "",        0, 0, 0, 0, 0 }
  91. };
  92.  
  93. struct map smapbf[SMAPSIZE];        /* local copy of swap allocation map */
  94. struct map cmapbf[CMAPSIZE];        /* local copy of core allocation map */
  95. int kmaxmem = 0;            /* local copy of maxmem */
  96. int kphysmem = 0;            /* local copy of physmem */
  97. int knswap = 0;                /* local copy of nswap */
  98.  
  99. int kmem = 0;                /* file handle for kernel memory */
  100. int delay = 1;                /* seconds between screen updates */
  101.  
  102. char dmap[MAX_ENTRIES] = 0;        /* display map */
  103.  
  104. int swap_scale = 1;            /* scale factor for swap map display */
  105. int core_scale = 1;            /* scale factor for core map display */
  106.  
  107. /*
  108.  * various useful definitions
  109.  */
  110. typedef int boolean;
  111.  
  112. /*#define    FALSE    0        /* defined in curses.h */
  113. /*#define    TRUE    1        /* defined in curses.h */
  114.  
  115. /*
  116.  * various function declarations
  117.  */
  118. extern long lseek();
  119. extern int read();
  120. extern time_t time();
  121.  
  122. /*
  123.  * interface to system error messages
  124.  */
  125. char *prog_name = NULL;
  126.  
  127. extern char *sys_errlist[];
  128. extern int sys_nerr;
  129. extern int errno;
  130.  
  131. /*
  132.  * error : performs a function similar to perror(3), but supports variable
  133.  * argument lists.  Prints out a formatted error string to stderr, followed if
  134.  * possible by an appropriate system error message.  Control is then
  135.  * returned to the system with an error status.  This function does not
  136.  * return.
  137.  */
  138. /* VARARGS0 */
  139. void error (va_alist)
  140. va_dcl                            /* varargs */
  141. {
  142.     int err;                      /* 1st arg - error number */
  143.     char *str;                    /* 2nd arg - error format string */
  144.     va_list args;
  145.     va_start(args);
  146.     err = va_arg (args, int);
  147.     str = va_arg (args, char *);
  148.     fprintf (stderr, "%s: ", prog_name);
  149.     vfprintf (stderr, str, args);
  150.     if (err != 0){
  151.     if (err <= sys_nerr && err > 0)
  152.             fprintf (stderr, " : %s\n", sys_errlist[err]);
  153.         else
  154.             fprintf (stderr, " : unknown error : %d\n", err);
  155.     }
  156.     va_end(args);
  157.     endwin();
  158.     exit(1);
  159. }
  160.  
  161. void version (){
  162.     printf ("\nKernel Allocation Map Display\n");
  163.     printf ("Version : 1.1 - 88/11/28 18:16:45, Patch Level %d\n", patch_level);
  164. }
  165.  
  166. void usage(){
  167.     version();
  168.     printf ("Usage : map [-[?h]] [-d#]\n\n");
  169.     printf ("\t-d#\tDelay '#' seconds between screen updates.  Defaults\n");
  170.     printf ("\t\tto 1 second.\n");
  171.     printf ("\t-h\tDisplays this message.\n");
  172.     printf ("\t-v\tDisplays version and patch level of program.\n");
  173.     printf ("\t-?\tDisplays this message.\n");
  174. }
  175.  
  176. /*
  177.  * get_nlist : fetches the required namelist from the kernel image
  178.  */
  179. void get_nlist(){
  180.     if (nlist ("/unix", namelist) != 0){
  181.         error (errno, "could not get namelist");
  182.     }
  183. }
  184.  
  185. /*
  186.  * open_kmem : opens kernel memory
  187.  */
  188. void open_kmem(){
  189.  
  190.     /*
  191.      * open kernel memory
  192.      */
  193.     if ((kmem=open ("/dev/kmem", O_RDONLY)) == -1){
  194.         error (errno, "could not open /dev/kmem");
  195.     }
  196. }
  197.  
  198. /*
  199.  * init_kmem : reads kernel memory to initialize various static values
  200.  * that are important for future processing.
  201.  */
  202. void init_kmem (){
  203.     /*
  204.      * fetch maxmem (maximum free memory available to a process)
  205.      */
  206.     if (lseek (kmem, namelist[MAX_MEM].n_value, 0) != namelist[MAX_MEM].n_value){
  207.         error (errno, "could not seek maxmem");
  208.     }
  209.     if (read (kmem, &kmaxmem, sizeof (int)) != sizeof (int)){
  210.         error (errno, "could not read maxmem");
  211.     }
  212.  
  213.     /*
  214.      * fetch physmem (maximum physical memory present in the system)
  215.      */
  216.     if (lseek (kmem, namelist[PHYS_MEM].n_value, 0) != namelist[PHYS_MEM].n_value){
  217.         error (errno, "could not seek physmem");
  218.     }
  219.     if (read (kmem, &kphysmem, sizeof (int)) != sizeof (int)){
  220.         error (errno, "could not read physmem");
  221.     }
  222.  
  223.     /*
  224.      * fetch nswap (total blocks in the swap device)
  225.      */
  226.     if (lseek (kmem, namelist[N_SWAP].n_value, 0) != namelist[N_SWAP].n_value){
  227.         error (errno, "could not seek nswap");
  228.     }
  229.     if (read (kmem, &knswap, sizeof (int)) != sizeof (int)){
  230.         error (errno, "could not read nswap");
  231.     }
  232.  
  233.     /*
  234.      * calculate the scale factor for the display maps.  The scale
  235.      * factors should be set in such a way that a single screen can
  236.      * display the entire map.  The scale factors are then massaged to
  237.      * ensure that they are always even.  This is done in multiple
  238.      * statements to ensure that smart compilers don't optimize the
  239.      * multiplies and divides away.  I'm sure there's a more elegant
  240.      * and reliable way, but this seems to work.
  241.      */
  242.     swap_scale = (knswap + MAX_ENTRIES - 1) / MAX_ENTRIES;
  243.     swap_scale = (swap_scale + 1) / 2;
  244.     swap_scale *= 2;
  245.     core_scale = (kphysmem + MAX_ENTRIES - 1) / MAX_ENTRIES;
  246.     core_scale = (core_scale + 1) / 2;
  247.     core_scale *= 2;
  248. }
  249.  
  250. /*
  251.  * read_map : copies the specified kernel allocation map into local memory
  252.  * for future processing.
  253.  */
  254. void read_map(loc, buf, size)
  255. daddr_t loc;                /* location in kernel to be read */
  256. struct map *buf;            /* buffer in which to place copy */
  257. unsigned size;                /* number of map entries to read */
  258. {
  259.     if (lseek (kmem, loc, 0) != loc){
  260.         error (errno, "could not seek kernel map");
  261.     }
  262.     if (read (kmem, buf, size*sizeof (struct map)) != size*sizeof (struct map)){
  263.         error (errno, "could not read kernel map");
  264.     }
  265. }
  266.  
  267. /*
  268.  * update_map : modifies all of the appropriate display map cells according
  269.  * that are affected by the specified kernel allocation map item.
  270.  */
  271. void update_map (dmap, mp, scale)
  272. char dmap[];
  273. struct map *mp;
  274. int scale;
  275. {
  276.     int entry;
  277.     int map_index;
  278.     int size;
  279.     size = mp->m_size;
  280.     for (entry = mp->m_addr; size; entry++){
  281.          map_index = entry / scale;
  282.         dmap[map_index] = 0;
  283.         size--;
  284.     }
  285. }
  286.  
  287. /*
  288.  * interpret_map : scans through the copy of the kernel allocation map and
  289.  * updates the specified display map accordingly.  The total number of free
  290.  * blocks in the map are returned.
  291.  */
  292. int interpret_map(dmap, kmp, scale)
  293. char dmap[];
  294. struct map *kmp;
  295. int scale;
  296. {
  297.     int total_free = 0;
  298.     struct map *mp;
  299.     memset (dmap, 1, MAX_ENTRIES);
  300.     for (mp = kmp; mp->m_size; mp++){
  301.         total_free += mp->m_size;
  302.         update_map (dmap, mp, scale);
  303.     }
  304.     return total_free;
  305. }
  306.  
  307. /*
  308.  * print_map : scans the allocation map, displaying it in the standard
  309.  * window.  Allocated cells are marked with an asterisk ('*'), and free
  310.  * cells are marked with a period ('.').
  311.  */
  312. void print_map(dmap, scale, total_size)
  313. char dmap[];
  314. int scale;
  315. long total_size;
  316. {
  317.     int i, j, k;
  318.     int entry;
  319.     move (2,0);
  320.     for (i = 0; i < MAX_ROWS; i++){
  321.         k = i*MAX_COLUMNS;
  322.         if (((long)k*scale) >= total_size)break;
  323.         printw ("%08lx:  ", (long)k * scale);
  324.         for (j = 0; j < MAX_COLUMNS; j++){
  325.             if ((((long)k+j)*scale) >= total_size)break;
  326.             entry = (i*MAX_COLUMNS+j);
  327.             if (dmap[entry] != 0)addch ('*');
  328.             else addch ('.');
  329.         }
  330.         addch ('\n');
  331.     }
  332. }
  333.  
  334. void interrupt (sig)
  335. int sig;
  336. {
  337.     move (0,0);
  338.     clrtobot();
  339.     refresh();
  340.     endwin();
  341.     exit(0);
  342. }
  343.  
  344. /*
  345.  * init : performs system and curses initialization
  346.  */
  347. void init (argc, argv)
  348. int argc;
  349. char *argv[];
  350. {
  351.     int i;
  352.     boolean done;
  353.     char *cp;
  354.  
  355.     /*
  356.      * before we go any further, disable interrupts
  357.      */
  358.     signal (SIGINT, SIG_IGN);
  359.     signal (SIGQUIT, SIG_IGN);
  360.     signal (SIGHUP, SIG_IGN);
  361.     signal (SIGTERM, SIG_IGN);
  362.  
  363.     /*
  364.      * save program name for future reference
  365.      */
  366.     prog_name = argv[0];
  367.  
  368.     for (i = 1; i < argc; i++){
  369.         cp = argv[i];
  370.         if (*cp == '-'){
  371.             done = FALSE;
  372.             while (*++cp && !done){
  373.                 switch (*cp){
  374.  
  375.                 case 'd':    /* delay */
  376.                     if (cp[1]){
  377.                         delay = atoi (++cp);
  378.                         done = TRUE;
  379.                     }
  380.                     else {
  381.                         delay = atoi (argv[++i]);
  382.                     }
  383.                     break;
  384.  
  385.                 case 'v':    /* display version */
  386.                     version();
  387.                     exit(0);
  388.  
  389.                 case '?':    /* usage */
  390.                 case 'h':
  391.                     usage();
  392.                     exit(0);
  393.  
  394.                 default:
  395.                     fprintf (stderr, "illegal option : %c; ignored.\n", *cp);
  396.                     break;
  397.                 }
  398.             }
  399.         }
  400.     }
  401.  
  402.     /*
  403.      * curses initialization
  404.      */
  405.     initscr();
  406.     cbreak();
  407.     noecho();
  408.     nodelay (stdscr, 1);
  409.  
  410.     /*
  411.      * print out a simple command menu
  412.      */
  413.     mvaddch (23, 0, '[');
  414.     attrset (A_BOLD);
  415.     addch ('m');
  416.     attroff (A_BOLD);
  417.     addch (',');
  418.     attrset (A_BOLD);
  419.     addch ('c');
  420.     attroff (A_BOLD);
  421.     addstr ("]=memory allocation map   [");
  422.     attrset (A_BOLD);
  423.     addch ('s');
  424.     attroff (A_BOLD);
  425.     addstr ("]=swap allocation map    [");
  426.     attrset (A_BOLD);
  427.     addch ('q');
  428.     attroff (A_BOLD);
  429.     addch (',');
  430.     attrset (A_BOLD);
  431.     addch ('x');
  432.     attroff (A_BOLD);
  433.     addch (',');
  434.     attrset (A_BOLD);
  435.     addch ('e');
  436.     attrset (A_NORMAL);
  437.     addstr ("]=exit");
  438.  
  439.     /*
  440.      * now that curses is initialized, catch the interrupt signal
  441.      * so we can die gracefully
  442.      */
  443.     signal (SIGINT, interrupt);
  444.     signal (SIGQUIT, interrupt);
  445.     signal (SIGHUP, interrupt);
  446.     signal (SIGTERM, interrupt);
  447.  
  448.     /*
  449.      * get ready to access kernel memory
  450.      */
  451.     open_kmem();
  452.     get_nlist ();
  453.     init_kmem();
  454. }
  455.  
  456. int main (argc, argv)
  457. int argc;
  458. char *argv[];
  459. {
  460.     struct tm *tmbuf;        /* to hold current time */
  461.     time_t tm;
  462.     boolean done = FALSE;        /* will be nonzero when ready to quit */
  463.     int mem_or_swap = 0;        /* 0 = display core map, 1 = swap map */
  464.     int free = 0;            /* free items in allocation map */
  465.  
  466.     init (argc, argv);
  467.     while (!done){
  468.  
  469.         /*
  470.          * get and display current time
  471.          */
  472.         time (&tm);
  473.         tmbuf = localtime (&tm);
  474.         move (0,0);
  475.         clrtoeol();
  476.         mvprintw (0, 67, "%02d:%02d:%02d", tmbuf->tm_hour, tmbuf->tm_min, tmbuf->tm_sec);
  477.  
  478.         if (mem_or_swap == 0){
  479.  
  480.             /*
  481.              * update and display core map
  482.              */
  483.             read_map (namelist[CORE_MAP].n_value, cmapbf, CMAPSIZE);
  484.             free = interpret_map (dmap, cmapbf, core_scale);
  485.             standout();
  486.             mvaddstr (0, 31, "Memory Allocation");
  487.             standend();
  488.             move (1,0);
  489.             clrtoeol();
  490.             mvprintw (1,  0, "Total Memory = %ld KBytes, %ld Kernel, %ld Free",
  491.                 ((long)kphysmem*NBPC)/1024,
  492.                 ((long)(kphysmem-kmaxmem)*NBPC)/1024, 
  493.                 ((long)free*NBPC)/1024);
  494.             mvprintw (1, 58, "Scale Factor = %2d", core_scale);
  495.             print_map (dmap, core_scale*NBPC, (long)kphysmem*NBPC);
  496.         }
  497.         else {
  498.  
  499.             /*
  500.              * update and display swap map
  501.              */
  502.             read_map (namelist[SWAP_MAP].n_value, smapbf, SMAPSIZE);
  503.             free = interpret_map (dmap, smapbf, swap_scale);
  504.             standout();
  505.             mvaddstr (0, 29, "Swap Device Allocation");
  506.             standend();
  507.             move (1,0);
  508.             clrtoeol();
  509.             mvprintw (1,  0, "Total swap space = %d Blocks, %d Free", knswap, free);
  510.             mvprintw (1, 58, "Scale Factor = % d", swap_scale);
  511.             print_map (dmap, swap_scale, (long)knswap);
  512.         }
  513.  
  514.         /*
  515.          * refresh the screen and wait a while
  516.          */
  517.         refresh();
  518.         sleep (delay);
  519.  
  520.         /*
  521.          * look for any new commands
  522.          */
  523.         switch (getch()){
  524.         case 'c':    /* switch to core (memory) map */
  525.         case 'm':
  526.             mem_or_swap = 0;
  527.             break;
  528.  
  529.         case 's':    /* switch to swap map */
  530.             mem_or_swap = 1;
  531.             break;
  532.  
  533.         case 'q':    /* quit */
  534.         case 'e':
  535.         case 'x':
  536.             done = TRUE;
  537.             break;
  538.  
  539.         default:    /* illegal command, ignore it */
  540.             break;
  541.         }
  542.             
  543.     }
  544.     move (0,0);
  545.     clrtobot();
  546.     refresh();
  547.     endwin();
  548. }
  549.  
  550.