Awe13.219 net.sources utzoo!decvax!harpo!floyd!vax135!lime!we13!rjk Mon Apr 19 19:45:39 1982 MEMAP: 11/70 RealTime Memory Map /*********************************************************************** * 11/70 MEMAP - REAL TIME MEMORY MAP * FILE 1 of 5 - README *********************************************************************** */ Memap is an active real-time (?) UNIX memory map. It displays the locations of processes in memory, updating changes once per second. A DEC VT100 with advanced video option is required for this program. Memaptest is a little demo program for memap. It is compiled with separate I/D space. Read the comment lines in the makefile; they tell you how to make the files. When completed, type the following for a demonstration: for X in 1 2 3 do sleep 10 /etc/memaptest done & /etc/memap This starts three of the demo programs so that the shared text segment can be seen. When all but the last one dies, the shared text will start flashing, then it will disappear with the death of the last one. For more info: Randy King WECo-Montgomery 8=392-4556 (we13!rjk) /*********************************************************************** * 11/70 MEMAP - REAL TIME MEMORY MAP * FILE 2 of 5 - Makefile *********************************************************************** */ # # Memap Makefile: `Make' must be executed as root. # # Specify your system maximum memory in the command line as: # make MEMORY=XXXXXXX # Where the X's are the decimal number of bytes of physical REAL # memory (printed at boot time as: real mem=XXXXXXX bytes). The # default size will be 11/70 maximum of 4 Megabytes. # # NOTE: Edit `memap.c' and set the define NPROC to at least the # number of slots in your process table. Default is 150. # # INSDIR is the directory where memap will reside. Normally, this # is /etc to keep it out of the public eye, although the public # can still use it. If you change INSDIR, you might also change # the SYNOPSIS in the manual page `memap.1'. # # RJKing WECo-MG6565 Sep 1981 # INSDIR=/etc MEMORY=4194304L MANDIR=/usr/man/local/man1 all: memap memaptest memap: $(CC) -DOURM=$(MEMORY) -O -n -s memap.c -o memap @if mv $(INSDIR)/memap $(INSDIR)/OLDmemap 2>/dev/null; \ then echo $(INSDIR)/memap moved to $(INSDIR)/OLDmemap; \ fi mv memap $(INSDIR)/memap chown root $(INSDIR)/memap chgrp bin $(INSDIR)/memap chmod 4775 $(INSDIR)/memap cp memap.1 $(MANDIR)/memap.1 chown bin $(MANDIR)/memap.1 chgrp bin $(MANDIR)/memap.1 chmod 664 $(MANDIR)/memap.1 memaptest: $(CC) -O -n -s memaptest.c -o memaptest @if mv $(INSDIR)/memaptest $(INSDIR)/OLDmemaptest 2>/dev/null; \ then echo $(INSDIR)/memaptest move to $(INSDIR)/OLDmemaptest; \ fi mv memaptest $(INSDIR)/memaptest chown bin $(INSDIR)/memaptest chgrp bin $(INSDIR)/memaptest chmod 775 $(INSDIR)/memaptest /*********************************************************************** * 11/70 MEMAP - REAL TIME MEMORY MAP * FILE 3 of 5 - memap.c *********************************************************************** */ /* Memap - Real time (?) UNIX memory map. This program produces a * real time display of the active system memory as near as can be * obtained. It is restricted to the VT100 terminal with advanced * video. RJKing WECO-MG6565 Sep 1981 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define NROW 23 /* # of rows in display */ #define NCOL 13 /* # of columns in display */ #define VOID (char *)0 /* Char NULL pointer */ #define NPROC 150 /* MAIN: Dimension for proc slots */ #define MAXM 4194304L /* MAIN: Max 11/70 MAIN memory */ #ifndef OURM #define OURM 3145728L /* MAIN: Our maximum memory */ #endif #define CSIZ (132 /NCOL) /* SHOW: Column width */ #define NSIZ (CSIZ -1) /* SHOW: Max process name length */ #define DRAW 001 /* SHOW[what]: Draw grid ticks */ #define ERAS 002 /* SHOW[what]: Erase at [addr] */ #define PRNT 004 /* SHOW[what]: Print at [addr] */ #define KERN 010000 /* SHOW[mode]: This proc is kernel */ #define TEXT 020000 /* SHOW[slot]: This proc has sep I/D */ #define DATA 040000 /* UPDATE[what]: update non-text */ #define ENDM 0001 /* SHOW: Screen position is END mark */ #define PRCM 0002 /* SHOW: Screen position is process */ #define TXTM 0004 /* SHOW: Screen position is text */ #define PROC 0 /* MAIN: Index to nl struct */ #define SBUF 1 /* MAIN: Index to nl struct */ #define ENDT 2 /* MAIN: Index to nl struct */ #define UTXS 3 /* MAIN: Index to nl struct */ #define TXTT 4 /* MAIN: Index to nl struct */ #define VARA 5 /* MAIN: Index to nl struct */ #define USER 6 /* MAIN: Index to nl struct */ #define NNLE 7 /* MAIN: Number of namelist entries */ int tmem,catch(); /* Signal catching routine */ char position[NROW][NCOL]; /* "position occupied" flags */ long maxmem=OURM; /* Default screen resolution */ struct nlist nl[] = { { "_proc" }, { "_sabuf" }, { "_etext" }, { "tstart" }, { "_text" }, { "_v" }, { "_u" }, { "" } }; struct savp { char p_stat, p_flag; short p_pid; ushort p_addr, p_size; ushort x_size, x_caddr; char x_count; } savp[NPROC]; struct proc newp; struct text newt; struct var var; struct user ub; char *getenv(),*strcpy(),*malloc(),*strncpy(),*strcat(),*strncat(),*ctime(); long lseek(),atol(),time(); unsigned sleep(); extern (*signal())(); extern optind,errno; extern char *optarg; main(argc,argv) char *argv[]; { register int i,slot; register char *tp; int smem,umem; long t,addr,size; struct utsname uts; unsigned mode; if(strcmp(getenv("TERM"), "vt100") != 0) { fprintf(stderr, "Term not vt100\n"); exit(1); } uname(&uts); smem = open("/dev/mem", O_RDONLY); umem = open("/dev/mem", O_RDONLY); tmem = open("/dev/mem", O_RDONLY); if(smem < 0 || umem < 0 || tmem < 0) { perror("/dev/mem"); exit(errno); } while((i = getopt(argc,argv,"t:m:")) != EOF) { switch(i) { case 't': maxmem = atol(optarg) *(long)(NCOL *NROW); break; case 'm': maxmem = atol(optarg); break; default: fprintf(stderr, "usage: %s [ -tTIKSIZ ] [ -mMEMSIZ ]\n", argv[0]); exit(1); } if(i == 't' || i == 'm') { i = strlen(optarg); if(optarg[i-1] == 'm' || optarg[i-1] == 'M') maxmem *= 1048576; if(optarg[i-1] == 'k' || optarg[i-1] == 'K') maxmem *= 1024; } } argc -= (optind -1); argv += (optind -1); if(maxmem > MAXM || maxmem < 1) { fprintf(stderr, "%d bytes out of range\n", maxmem); exit(1); } for(i=1; i<=NSIG; ++i) signal(i, catch); nlist("/unix", nl); for(i=0; i NPROC) { fprintf(stderr, "NPROC define must be at least %d\n", var.v_proc); exit(1); } if(NPROC > var.v_proc +25) { fprintf(stderr, "NPROC define wasting memory; should be around %d\n", var.v_proc); sleep(5); } show(DRAW, VOID, 0L, 0L, NULL); show(PRNT, "Proctbl", (long)nl[PROC].n_value, 0L, KERN); show(PRNT, "_sabufs", (long)nl[SBUF].n_value, 0L, KERN); show(PRNT, "EndOfText", (long)nl[ENDT].n_value, 0L, KERN); show(PRNT, uts.sysname, (long)nl[UTXS].n_value, 0L, KERN); addr = (long)(nl[USER].n_value + USIZE *64); show(PRNT, "Stack_Top", addr, 0L, KERN); i = nice(0); nice(-i); for(;;) { if(lseek(smem, (long)nl[PROC].n_value, 0) < 0) fatalerr("seek to process table"); for(slot=0; slot= 1)) { addr = ctob((long)savp[slot].x_caddr); size = ctob((long)savp[slot].x_size); show(ERAS, VOID, addr, size, NULL); savp[slot].x_count = 0; } } if((newp.p_flag &SLOAD) == 0) { clearout(slot); continue; } if(newp.p_addr) { addr = ctob((long)newp.p_addr); size = ctob((long)newp.p_size); mode = (unsigned)(newp.p_flag &0377); mode |= ((newp.p_stat <<8) &07400); if(lseek(umem, addr, 0) < 0) fatalerr("seek to user block"); if(read(umem, (char *)&ub, sizeof(ub)) < 0) fatalerr("read user block"); show(PRNT, ub.u_comm, addr, size, mode); if(ub.u_tsize && getextdata()) { addr = ctob((long)newt.x_caddr); size = ctob((long)newt.x_size); mode = TEXT; show(PRNT, ub.u_comm, addr, size, mode); update(TEXT, slot); } } update(DATA, slot); } time(&t); tp = ctime(&t); *(tp+19) = NULL; printf("\33[24;59H%s", tp+11); sleep(1); } } show(what, name, addr, size, mode) char *name; long addr, size; unsigned mode; { register int i,swap=0; static int ticks; int srow, scol, erow, ecol, srpos, scpos, erpos, ecpos; char pnam[32],flag,stat; long check; if(what &DRAW) { ticks = (int) (maxmem / ((long)(NCOL *NROW))); printf("\33<\33[?3h"); sleep(1); printf("\33[2J\33[24H\33#6"); printf("%d Bytes/Tick (%.2f Meg) ", ticks, (double)maxmem /1048576.0); printf("\33[1;7mText\33[m \33[4mLocked\33[m "); printf("\33[7mSpecial\33[m \33[1mRunnable\33[m\33(0"); for(scol=1; scol<=NCOL; ++scol) { printf("\33[1;%dH", (NCOL -3) *(scol -1) +1); for(srow=1; srow<=NROW; ++srow) { if(srow == 1) printf("l\b\33D"); else if(srow == NROW) printf("m"); else printf("t\b\33D"); } } printf("\33(B\33[24H\33[m"); } flag = (char)(mode &0377); stat = (char)((mode &07400) >>8); check = (addr /(long)ticks) +1L; if(check > (long)(NROW *NCOL)) return; srow = (int)check; check = ((addr +size) /(long)ticks) +1L; if(check > (long)(NROW *NCOL)) return; erow = (int)check; for(scol=0; srow>NROW; ++scol) srow -= NROW; srpos = srow -1; scpos = scol; scol = (scol *CSIZ) +2; for(ecol=0; erow>NROW; ++ecol) erow -= NROW; erpos = erow -1; ecpos = ecol; ecol = (ecol *CSIZ) +2; if(*name == NULL) { if(newp.p_pid == 0) name = "swapper"; else { name = "SWAPPING"; ++swap; } } if(what &ERAS) { printf("\33[%d;%dH\33[%d;%dH", srow, scol, srow, scol); for(i=0; i