core and swap map program needed

Stacey Campbell staceyc at sco.COM
Fri Jun 15 03:38:29 AEST 1990


In article <1929 at bnlux0.bnl.gov> scottc at bnlux0.bnl.gov (david scott coburn) writes:
>I am looking for a program that will display information on how core
>and swap memory is being used.
>
>A nice visual representation of the allocations would be nice, but not
>neccesary.
>
>I would also be interested in any information on where and how the kernel
>stores the lists of available and used core and swap memory.

Here's a program to display such things.  It uses the latest color curses
on System V.3.2, and compiles and runs on an AT&T 3b2 and SCO Unix/386.
It will almost certainly run under Interactive's 386 V.3.2 port.
The program is pre-pre-alpha, the code's not buggy, just ugly in spots.
Eventually a rewrite with bulk extensions will be submitted to one of
the source groups, so comments on this sucker would be appreciated.

It displays cpu usage, free RAM, free swap pages, pages swapped in
since boot, maximum RAM, size of runqueue etc.  It looks good on a
color terminal or console, but is also quite presentable on a normal
terminal.

It needs to read /unix and /dev/kmem which are nicely hardwired into
the code.  It does updates every 5 seconds (also hardwired), you may
want to increase that to at least 10+.

Have fun,

Stacey Campbell

#!/bin/sh
# this is a shell archive
#
# This archive contains:
#	Makefile
#	mon.c
#	color.c
#	consts.h
#	funcs.h
#
PATH=/bin:$PATH
echo 'mshar: extracting Makefile (size: 146)'
sed 's/^X//' << 'GURK' > Makefile &&
XOBJS= mon.o color.o
XEXE= mon
XCFLAGS= -g
XLDLIBS= -lcurses
X
X$(EXE): $(OBJS)
X	cc $(CFLAGS) $(OBJS) -o $(EXE) $(LDLIBS)
X
Xclean:
X	rm -f $(EXE) $(OBJS)
GURK
chmod 0644 Makefile || echo 'restore of Makefile fails'
echo 'mshar: extracting mon.c (size: 10687)'
sed 's/^X//' << 'GURK' > mon.c &&
X#include <fcntl.h>
X#include <a.out.h>
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/sysinfo.h>
X#include <sys/sysmacros.h>
X#include <sys/immu.h>
X#include <sys/utsname.h>
X#include <errno.h>
X#include <curses.h>
X#include "consts.h"
X
X#define CPU_INFO_SZ (sizeof(sysinfo.cpu) / sizeof(sysinfo.cpu[0]))
X#define DEFAULT_HZ "60"
X
X#define GRPH_LINES 9
X#define GRPH_COLS 20
X#define MAP_LINES (GRPH_LINES - 2)
X#define MAP_COLS (GRPH_COLS - 1)
X
X#define DEFAULT_REFRESH 5
X#define HEADER "Monitor"
X
Xextern long lseek();
Xextern char *getenv();
X
Xextern int GreenBlackPair;
Xextern int RedBlackPair;
X
X
Xstruct sysinfo sysinfo;  /* need to declare these to deal with sys/sysinfo.h */
Xtime_t lbolt;            /* extern declarations */
Xstruct minfo minfo;
Xint nswap;
Xint maxmem;
Xint freemem;
X
Xstatic struct nlist NlistInfo[] = {
X#define NL_SYSINFO 0
X	{"sysinfo"},
X#define NL_LBOLT 1
X	{"lbolt"},
X#define NL_MINFO 2
X	{"minfo"},
X#define NL_NSWAP 3
X	{"nswap"},
X#define NL_FREEMEM 4
X	{"freemem"},
X#define NL_MAXMEM 5
X	{"maxmem"},
X	{0}};
X
Xtypedef WINDOW * display_t;
Xtypedef struct cpu_stats_t {
X	double user;
X	double kernel;
X	double idle;
X	} cpu_stats_t;
Xtypedef struct grph_win_t {
X	WINDOW *back;
X	WINDOW *top;
X	int col;
X	} grph_win_t;
X
X#ifdef DEBUG
X#define sleep(n) {time_t d = time((time_t *)0) + n ; while\
X    (d >= time((time_t *)0));}
X#endif
X
Xstatic int NlistLoaded = 0;
Xstatic int KmemFd;
Xstatic time_t SavedCpu[CPU_INFO_SZ];
Xstatic time_t BootTime;
Xstatic int Hertz;
Xstatic time_t Now;
Xstatic int OptNoColor = 0;
X
Xstatic void DisplayAdd();
Xstatic void InitGraphWin();
Xstatic void UpdateGraph();
Xstatic void XtraInfoFn();
X
Xint main(argc, argv)
X
Xint argc;
Xchar *argv[];
X
X	{
X	char head[sizeof(HEADER) + sizeof(struct utsname) + 32];
X	struct utsname name;
X	grph_win_t user_win, kernel_win, swap_win, mem_win;
X	cpu_stats_t cpu_stats;
X	double free_swap;
X	double free_memory;
X
X	if (uname(&name) == -1)
X		{
X		perror(argv[0]);
X		exit(1);
X		}
X	initscr();
X	waddstr(stdscr, "initialising...");
X	wrefresh(stdscr);
X	if (start_color() != OK)
X		OptNoColor = 1;
X	else
X		if (! has_colors())
X			OptNoColor = 1;
X		else
X			ColorMapInit();
X	Now = time((time_t *)0);
X	if (! NlistFnInit(stdscr))
X		exit(1);
X	wmove(stdscr, 0, 0);
X	wclrtoeol(stdscr);
X	mvwaddstr(stdscr, 0, 0, "wait...");
X	wrefresh(stdscr);
X	InitGraphWin(&user_win, 2, 0, "User CPU %");
X	InitGraphWin(&kernel_win, 2, GRPH_COLS + 2, "Kernel CPU %");
X	InitGraphWin(&swap_win, 2, (GRPH_COLS + 2) * 2, "Free swap pages %");
X	InitGraphWin(&mem_win, 2 + GRPH_LINES + 1, 0, "Free memory %");
X	sleep(2);
X	curs_set(FALSE);
X	werase(stdscr);
X	sprintf(head, "%s - %s %s Unix %s.%s", HEADER, name.sysname,
X	    name.machine, name.release, name.version);
X	wstandout(stdscr);
X	mvwaddstr(stdscr, 0, (COLS - strlen(head)) / 2 - 1, head);
X	wstandend(stdscr);
X	wrefresh(stdscr);
X	wrefresh(user_win.back);
X	wrefresh(kernel_win.back);
X	wrefresh(swap_win.back);
X	wrefresh(mem_win.back);
X	for (;;)
X		{
X		Now = time((time_t *)0);
X		(void)NlistFn(stdscr, &cpu_stats);
X		XtraInfoFn(stdscr, &free_swap, &free_memory);
X		UpdateGraph(&user_win, cpu_stats.user, FIELD_HOT);
X		UpdateGraph(&kernel_win, cpu_stats.kernel, FIELD_HOT);
X		UpdateGraph(&swap_win, free_swap, FIELD_COLD);
X		UpdateGraph(&mem_win, free_memory, FIELD_COLD);
X		wmove(stdscr, LINES - 1, 0);
X		wrefresh(stdscr);
X		sleep(DEFAULT_REFRESH);
X		}
X	endwin();
X	}
X
Xstatic void XtraInfoFn(win, free_swap, free_memory)
X
XWINDOW *win;
Xdouble *free_swap;
Xdouble *free_memory;
X
X	{
X	if (lseek(KmemFd, NlistInfo[NL_MINFO].n_value, 0) == -1L)
X		{
X		DisplayAdd(win, "kmem lseek error ");
X		flash();
X		return;
X		}
X	if (read(KmemFd, (char *)&minfo, sizeof(minfo)) < 0)
X		{
X		DisplayAdd(win, "kmem read error ");
X		flash();
X		return;
X		}
X	if (lseek(KmemFd, NlistInfo[NL_FREEMEM].n_value, 0) == -1L)
X		{
X		DisplayAdd(win, "kmem lseek error ");
X		flash();
X		return;
X		}
X	if (read(KmemFd, (char *)&freemem, sizeof(freemem)) < 0)
X		{
X		DisplayAdd(win, "kmem read error ");
X		flash();
X		return;
X		}
X	wmove(win, LINES - 3, 0);
X	wprintw(win, "free swap: %ld nswap: %ld maxmem: %ld freemem: %ld      ",
X	    minfo.freeswap, nswap, ctob(maxmem) / NBPP, freemem);
X	*free_swap = minfo.freeswap / (double)nswap;
X	*free_memory = freemem / (double)(ctob(maxmem) / NBPP);
X	wrefresh(win);
X	}
X
Xstatic void UpdateGraph(grph_win, level, field)
X
Xgrph_win_t *grph_win;
Xdouble level;
Xint field;
X
X	{
X	int i;
X	int spot_y, spot_x;
X	double scale;
X
X	spot_y = (double)MAP_LINES - (level * (double)MAP_LINES)
X	    + 0.5;
X	if (spot_y >= MAP_LINES)
X		spot_y = MAP_LINES - 1;
X	else
X		if (spot_y < 0)
X			spot_y = 0;
X	spot_x = grph_win->col;
X	if (spot_x >= MAP_COLS)
X		{
X		spot_x = MAP_COLS - 1;
X		for (i = 0; i < MAP_LINES; ++i)
X			mvwdelch(grph_win->top, i, 0);
X		}
X	grph_win->col = spot_x + 1;
X	if (OptNoColor)
X		{
X		wstandout(grph_win->top);
X		for (i = spot_y; i < MAP_LINES; ++i)
X			mvwaddch(grph_win->top, i, spot_x, ' ');
X		wstandend(grph_win->top);
X		}
X	else
X		for (i = spot_y; i < MAP_LINES; ++i)
X			{
X			scale = 1.0 - i / (double)(MAP_LINES - 1);
X			FillColor(grph_win->top, scale, i, spot_x, field);
X			}
X	wrefresh(grph_win->top);
X	}
X
Xint NlistFnInit(display)
X
Xdisplay_t *display;
X
X	{
X	int i;
X	char *hz_str;
X	struct sysinfo sysinfo;
X	static int kmem_status = 0;
X
X	if (! NlistLoaded)
X		{
X		NlistLoaded = 1;
X		if (nlist("/unix", NlistInfo) < 0)
X			{
X			DisplayAdd(display, "nlist error ");
X			return 0;
X			}
X		if (NlistInfo[NL_SYSINFO].n_value == 0)
X			{
X			DisplayAdd(display, "bad sysinfo offset ");
X			flash();
X			return 0;
X			}
X		if (NlistInfo[NL_LBOLT].n_value == 0)
X			{
X			DisplayAdd(display, "bad lbolt offset ");
X			flash();
X			return 0;
X			}
X		if (! (hz_str = getenv("HZ")))
X			hz_str = DEFAULT_HZ;
X		Hertz = atoi(hz_str);
X		if ((KmemFd = open("/dev/kmem", O_RDONLY)) < 0)
X			{
X			DisplayAdd(display, "cannot open kmem ");
X			return 0;
X			}
X		if (lseek(KmemFd, NlistInfo[NL_SYSINFO].n_value, 0) == -1L)
X			{
X			char buf[128];
X			extern char *sys_errlist[];
X
X			sprintf(buf, "kmem lseek error %d %s %u ", errno,
X			    sys_errlist[errno], NlistInfo[NL_SYSINFO].n_value);
X			DisplayAdd(display, buf);
X			flash();
X			return 0;
X			}
X		if (read(KmemFd, (char *)&sysinfo, sizeof(sysinfo)) < 0)
X			{
X			DisplayAdd(display, "kmem read error ");
X			flash();
X			return 0;
X			}
X		for (i = 0; i < CPU_INFO_SZ; ++i)
X			SavedCpu[i] = sysinfo.cpu[i];
X		if (lseek(KmemFd, NlistInfo[NL_MINFO].n_value, 0) == -1L)
X			{
X			char buf[128];
X			extern char *sys_errlist[];
X
X			sprintf(buf, "kmem lseek error %d %s %u ", errno,
X			    sys_errlist[errno], NlistInfo[NL_MINFO].n_value);
X			DisplayAdd(display, buf);
X			flash();
X			return 0;
X			}
X		if (read(KmemFd, (char *)&minfo, sizeof(minfo)) < 0)
X			{
X			DisplayAdd(display, "kmem read error ");
X			flash();
X			return 0;
X			}
X		if (lseek(KmemFd, NlistInfo[NL_NSWAP].n_value, 0) == -1L)
X			{
X			char buf[128];
X			extern char *sys_errlist[];
X
X			sprintf(buf, "kmem lseek error %d %s %u ", errno,
X			    sys_errlist[errno], NlistInfo[NL_NSWAP].n_value);
X			DisplayAdd(display, buf);
X			flash();
X			return 0;
X			}
X		if (read(KmemFd, (char *)&nswap, sizeof(nswap)) < 0)
X			{
X			DisplayAdd(display, "kmem read error ");
X			flash();
X			return 0;
X			}
X		if (lseek(KmemFd, NlistInfo[NL_MAXMEM].n_value, 0) == -1L)
X			{
X			char buf[128];
X			extern char *sys_errlist[];
X
X			sprintf(buf, "kmem lseek error %d %s %u ", errno,
X			    sys_errlist[errno], NlistInfo[NL_MAXMEM].n_value);
X			DisplayAdd(display, buf);
X			flash();
X			return 0;
X			}
X		if (read(KmemFd, (char *)&maxmem, sizeof(maxmem)) < 0)
X			{
X			DisplayAdd(display, "kmem read error ");
X			flash();
X			return 0;
X			}
X
X		kmem_status = 1;
X		}
X
X	return kmem_status;
X	}
X
Xint NlistFn(display, cpu_stats)
X
Xdisplay_t *display;
Xcpu_stats_t *cpu_stats;
X
X	{
X	int i;
X	time_t all_krn;
X	struct sysinfo sysinfo;
X	time_t new_cpu[CPU_INFO_SZ];
X	double total_cpu;
X
X	if (lseek(KmemFd, NlistInfo[NL_SYSINFO].n_value, 0) == -1L)
X		{
X		DisplayAdd(display, "kmem lseek error ");
X		flash();
X		return 0;
X		}
X	if (read(KmemFd, (char *)&sysinfo, sizeof(sysinfo)) < 0)
X		{
X		DisplayAdd(display, "kmem read error ");
X		flash();
X		return 0;
X		}
X
X	total_cpu = 0.0;
X	for (i = 0; i < CPU_INFO_SZ; ++i)
X		{
X		total_cpu += new_cpu[i] = sysinfo.cpu[i] - SavedCpu[i];
X		SavedCpu[i] = sysinfo.cpu[i];
X		}
X
X	cpu_stats->user = new_cpu[CPU_USER] / total_cpu;
X#ifndef PARTIAL
X	all_krn = new_cpu[CPU_KERNEL] + new_cpu[CPU_WAIT] + new_cpu[CPU_SXBRK];
X#else
X	all_krn = new_cpu[CPU_KERNEL];
X#endif
X	cpu_stats->kernel = all_krn / total_cpu;
X	cpu_stats->idle = new_cpu[CPU_IDLE] / total_cpu;
X	wmove(stdscr, LINES - 2, 0);
X	wprintw(stdscr, "swapin: %ld", sysinfo.swapin);
X	wmove(stdscr, LINES - 1, 0);
X	wprintw(stdscr, "runque: %ld", sysinfo.runque);
X	wrefresh(stdscr);
X
X	return 1;
X	}
X
Xint UptimeFnInit(display)
X
Xdisplay_t *display;
X
X	{
X	time_t lbolt;                     /* a contraction of lightning bolt */
X
X	if (NlistFnInit(display) == 0)
X		return 0;
X
X	if (lseek(KmemFd, NlistInfo[NL_LBOLT].n_value, 0) == -1L)
X		{
X		DisplayAdd(display, "kmem lbolt lseek error ");
X		flash();
X		return 0;
X		}
X	if (read(KmemFd, (char *)&lbolt , sizeof(lbolt)) < 0)
X		{
X		DisplayAdd(display, "kmem lbolt read error ");
X		flash();
X		return 0;
X		}
X
X	BootTime = Now - lbolt / Hertz;
X	if (BootTime < 0)
X		DisplayAdd(display, "very strange boottime ");
X
X	return 1;
X	}
X
Xint UptimeFn(display)
X
Xdisplay_t *display;
X
X	{
X	time_t lbolt;
X	time_t uptime;
X	int days, hours, minutes, seconds;
X	char buf[64];
X
X	uptime = Now - BootTime;
X	days = uptime / (60 * 60 * 24);
X	uptime -= days * (60 * 60 * 24);
X	hours = uptime / (60 * 60);
X	uptime -= hours * (60 * 60);
X	minutes = uptime / 60;
X	uptime -= minutes * 60;
X	seconds = uptime;
X	sprintf(buf, "ut: %d+%.2d:%.2d:%.2d ", days, hours, minutes, seconds);
X	DisplayAdd(display, buf);
X
X	return 1;
X	}
X
Xstatic void DisplayAdd(display, msg)
X
XWINDOW *display;
Xchar *msg;
X
X	{
X	wprintw(stdscr, "%s\n", msg);
X	wrefresh(stdscr);
X	}
X
Xstatic void InitGraphWin(win, start_y, start_x, label)
X
Xgrph_win_t *win;
Xint start_y;
Xint start_x;
Xchar *label;
X
X	{
X	int i, j;
X	int len;
X
X	win->back = newwin(GRPH_LINES, GRPH_COLS, start_y, start_x);
X	if (! OptNoColor)
X		wattron(win->back, COLOR_PAIR(GreenBlackPair));
X	for (i = 0; i < MAP_LINES + 1; ++i)
X		mvwaddch(win->back, i, 0, ACS_VLINE);
X	for (i = 0; i < MAP_COLS + 1; ++i)
X		mvwaddch(win->back, MAP_LINES, i, ACS_HLINE);
X	mvwaddch(win->back, MAP_LINES, 0, ACS_LLCORNER);
X	if (! OptNoColor)
X		wattroff(win->back, COLOR_PAIR(GreenBlackPair));
X	win->top = newwin(MAP_LINES, MAP_COLS, start_y, start_x + GRPH_COLS
X	    - MAP_COLS);
X	win->col = 0;
X	len = strlen(label);
X	if (! OptNoColor)
X		wattron(win->back, COLOR_PAIR(RedBlackPair));
X	mvwaddstr(win->back, GRPH_LINES - 1, (GRPH_COLS - len) / 2, label);
X	if (! OptNoColor)
X		wattroff(win->back, COLOR_PAIR(RedBlackPair));
X	}
GURK
chmod 0644 mon.c || echo 'restore of mon.c fails'
echo 'mshar: extracting color.c (size: 1688)'
sed 's/^X//' << 'GURK' > color.c &&
X#include <curses.h>
X#include "consts.h"
X
X#define PAIR_COUNT (sizeof(PairsList) / sizeof(PairsList[0]))
X#define PR_CNT2ID(pair) ((pair) + 1)
X
Xextern char *malloc();
X
Xint GreenBlackPair;
Xint RedBlackPair;
Xstatic int ColdPair;
X
Xtypedef struct pairs_t {
X	unsigned long fg;
X	unsigned long bg;
X	} pairs_t;
X
Xstatic pairs_t PairsList[] = {
X	{COLOR_BLACK, COLOR_YELLOW},
X	{COLOR_BLACK, COLOR_RED},
X	{COLOR_BLACK, COLOR_MAGENTA}};
X
Xvoid ColorMapInit()
X
X	{
X	int i;
X	int id;
X
X	for (i = 0; i < PAIR_COUNT; ++i)
X		{
X		id = PR_CNT2ID(i);
X		if (init_pair(id, PairsList[i].fg, PairsList[i].bg) != OK)
X			{
X			endwin();
X			fprintf(stderr, "init_pair: %d failed\n", id);
X			exit(0);
X			}
X		}
X	GreenBlackPair = PR_CNT2ID(PAIR_COUNT);
X	if (init_pair(GreenBlackPair, COLOR_GREEN, COLOR_BLACK) != OK)
X		{
X		endwin();
X		fprintf(stderr, "init_pair: %d failed\n", GreenBlackPair);
X		exit(0);
X		}
X	ColdPair = PR_CNT2ID(PAIR_COUNT + 1);
X	if (init_pair(ColdPair, COLOR_BLACK, COLOR_CYAN) != OK)
X		{
X		endwin();
X		fprintf(stderr, "init_pair: %d failed\n", ColdPair);
X		exit(0);
X		}
X	RedBlackPair = PR_CNT2ID(PAIR_COUNT + 2);
X	if (init_pair(RedBlackPair, COLOR_RED, COLOR_BLACK) != OK)
X		{
X		endwin();
X		fprintf(stderr, "init_pair: %d failed\n", RedBlackPair);
X		exit(0);
X		}
X	}
X
Xint FillColor(win, scale, y, x, field)
X
XWINDOW *win;
Xdouble scale;
Xint y, x;
Xint field;
X
X	{
X	int pair;
X	int pair_id;
X
X	if (field == FIELD_HOT)
X		{
X		pair = scale * (double)PAIR_COUNT;
X		if (pair >= PAIR_COUNT)
X			pair = PAIR_COUNT - 1;
X		else
X			if (pair < 0)
X				pair = 0;
X		pair_id = PR_CNT2ID(pair);
X		}
X	else
X		pair_id = ColdPair;
X
X	wattron(win, COLOR_PAIR(pair_id));
X	mvwaddch(win, y, x, ' ');
X	wattroff(win, COLOR_PAIR(pair_id));
X	}
GURK
chmod 0644 color.c || echo 'restore of color.c fails'
echo 'mshar: extracting consts.h (size: 41)'
sed 's/^X//' << 'GURK' > consts.h &&
X#define FIELD_HOT 0
X#define FIELD_COLD 1
GURK
chmod 0644 consts.h || echo 'restore of consts.h fails'
echo 'mshar: extracting funcs.h (size: 39)'
sed 's/^X//' << 'GURK' > funcs.h &&
Xvoid ColorMapInit();
Xvoid FillColor();
GURK
chmod 0644 funcs.h || echo 'restore of funcs.h fails'
exit 0
-- 
Stacey Campbell       staceyc at sco.com
{uunet,decwrl,ucscc,att,sq,altos,lotus,phoenix,sun,microsoft,xbs}!sco!staceyc



More information about the Comp.unix.i386 mailing list