⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stats.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <ctype.h>#include <auth.h>#include <fcall.h>#include <draw.h>#include <event.h>#define	MAXNUM	10	/* maximum number of numbers on data line */typedef struct Graph	Graph;typedef struct Machine	Machine;struct Graph{	int		colindex;	Rectangle	r;	int		*data;	int		ndata;	char		*label;	void		(*newvalue)(Machine*, ulong*, ulong*, int);	void		(*update)(Graph*, ulong, ulong);	Machine		*mach;	int		overflow;	Image		*overtmp;};enum{	/* old /dev/swap */	Mem		= 0,	Maxmem,	Swap,	Maxswap,		/* /dev/sysstats */	Procno	= 0,	Context,	Interrupt,	Syscall,	Fault,	TLBfault,	TLBpurge,	Load,	Idle,	InIntr,	/* /net/ether0/stats */	In		= 0,	Link,	Out,	Err0,};struct Machine{	char		*name;	int		remote;	int		statsfd;	int		swapfd;	int		etherfd;	int		ifstatsfd;	int		batteryfd;	int		bitsybatfd;	int		disable;	ulong		devswap[4];	ulong		devsysstat[10];	ulong		prevsysstat[10];	int		nproc;	ulong		netetherstats[8];	ulong		prevetherstats[8];	ulong		batterystats[2];	ulong		netetherifstats[2];	char		buf[1024];	char		*bufp;	char		*ebufp;};enum{	Mainproc,	Mouseproc,	NPROC,};enum{	Ncolor		= 6,	Ysqueeze	= 2,	/* vertical squeezing of label text */	Labspace	= 2,	/* room around label */	Dot		= 2,	/* height of dot */	Opwid		= 5,	/* strlen("add  ") or strlen("drop ") */	Nlab		= 3,	/* max number of labels on y axis */	Lablen		= 16,	/* max length of label */	Lx		= 4,	/* label tick length */};enum Menu2{	Mbattery,	Mcontext,	Mether,	Methererr,	Metherin,	Metherout,	Mfault,	Midle,	Minintr,	Mintr,	Mload,	Mmem,	Mswap,	Msyscall,	Mtlbmiss,	Mtlbpurge,	Msignal,	Nmenu2,};char	*menu2str[Nmenu2+1] = {	"add  battery ",	"add  context ",	"add  ether   ",	"add  ethererr",	"add  etherin ",	"add  etherout",	"add  fault   ",	"add  idle    ",	"add  inintr  ",	"add  intr    ",	"add  load    ",	"add  mem     ",	"add  swap    ",	"add  syscall ",	"add  tlbmiss ",	"add  tlbpurge",	"add  802.11b ",	nil,};void	contextval(Machine*, ulong*, ulong*, int),	etherval(Machine*, ulong*, ulong*, int),	ethererrval(Machine*, ulong*, ulong*, int),	etherinval(Machine*, ulong*, ulong*, int),	etheroutval(Machine*, ulong*, ulong*, int),	faultval(Machine*, ulong*, ulong*, int),	intrval(Machine*, ulong*, ulong*, int),	inintrval(Machine*, ulong*, ulong*, int),	loadval(Machine*, ulong*, ulong*, int),	idleval(Machine*, ulong*, ulong*, int),	memval(Machine*, ulong*, ulong*, int),	swapval(Machine*, ulong*, ulong*, int),	syscallval(Machine*, ulong*, ulong*, int),	tlbmissval(Machine*, ulong*, ulong*, int),	tlbpurgeval(Machine*, ulong*, ulong*, int),	batteryval(Machine*, ulong*, ulong*, int),	signalval(Machine*, ulong*, ulong*, int);Menu	menu2 = {menu2str, nil};int	present[Nmenu2];void	(*newvaluefn[Nmenu2])(Machine*, ulong*, ulong*, int init) = {	batteryval,	contextval,	etherval,	ethererrval,	etherinval,	etheroutval,	faultval,	idleval,	inintrval,	intrval,	loadval,	memval,	swapval,	syscallval,	tlbmissval,	tlbpurgeval,	signalval,};Image	*cols[Ncolor][3];Graph	*graph;Machine	*mach;Font	*mediumfont;char	*mysysname;char	argchars[] = "8bceEfiImlnpstw";int	pids[NPROC];int 	parity;	/* toggled to avoid patterns in textured background */int	nmach;int	ngraph;	/* totaly number is ngraph*nmach */double	scale = 1.0;int	logscale = 0;int	ylabels = 0;int	oldsystem = 0;int 	sleeptime = 1000;char	*procnames[NPROC] = {"main", "mouse"};voidkillall(char *s){	int i, pid;	pid = getpid();	for(i=0; i<NPROC; i++)		if(pids[i] && pids[i]!=pid)			postnote(PNPROC, pids[i], "kill");	exits(s);}void*emalloc(ulong sz){	void *v;	v = malloc(sz);	if(v == nil) {		fprint(2, "stats: out of memory allocating %ld: %r\n", sz);		killall("mem");	}	memset(v, 0, sz);	return v;}void*erealloc(void *v, ulong sz){	v = realloc(v, sz);	if(v == nil) {		fprint(2, "stats: out of memory reallocating %ld: %r\n", sz);		killall("mem");	}	return v;}char*estrdup(char *s){	char *t;	if((t = strdup(s)) == nil) {		fprint(2, "stats: out of memory in strdup(%.10s): %r\n", s);		killall("mem");	}	return t;}voidmkcol(int i, int c0, int c1, int c2){	cols[i][0] = allocimagemix(display, c0, DWhite);	cols[i][1] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, c1);	cols[i][2] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, c2);}voidcolinit(void){	mediumfont = openfont(display, "/lib/font/bit/pelm/latin1.8.font");	if(mediumfont == nil)		mediumfont = font;	/* Peach */	mkcol(0, 0xFFAAAAFF, 0xFFAAAAFF, 0xBB5D5DFF);	/* Aqua */	mkcol(1, DPalebluegreen, DPalegreygreen, DPurpleblue);	/* Yellow */	mkcol(2, DPaleyellow, DDarkyellow, DYellowgreen);	/* Green */	mkcol(3, DPalegreen, DMedgreen, DDarkgreen);	/* Blue */	mkcol(4, 0x00AAFFFF, 0x00AAFFFF, 0x0088CCFF);	/* Grey */	cols[5][0] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xEEEEEEFF);	cols[5][1] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xCCCCCCFF);	cols[5][2] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x888888FF);}intloadbuf(Machine *m, int *fd){	int n;	if(*fd < 0)		return 0;	seek(*fd, 0, 0);	n = read(*fd, m->buf, sizeof m->buf-1);	if(n <= 0){		close(*fd);		*fd = -1;		return 0;	}	m->bufp = m->buf;	m->ebufp = m->buf+n;	m->buf[n] = 0;	return 1;}voidlabel(Point p, int dy, char *text){	char *s;	Rune r[2];	int w, maxw, maxy;	p.x += Labspace;	maxy = p.y+dy;	maxw = 0;	r[1] = '\0';	for(s=text; *s; ){		if(p.y+mediumfont->height-Ysqueeze > maxy)			break;		w = chartorune(r, s);		s += w;		w = runestringwidth(mediumfont, r);		if(w > maxw)			maxw = w;		runestring(screen, p, display->black, ZP, mediumfont, r);		p.y += mediumfont->height-Ysqueeze;	}}Pointparitypt(int x){	return Pt(x+parity, 0);}Pointdatapoint(Graph *g, int x, ulong v, ulong vmax){	Point p;	double y;	p.x = x;	y = ((double)v)/(vmax*scale);	if(logscale){		/*		 * Arrange scale to cover a factor of 1000.		 * vmax corresponds to the 100 mark.		 * 10*vmax is the top of the scale.		 */		if(y <= 0.)			y = 0;		else{			y = log10(y);			/* 1 now corresponds to the top; -2 to the bottom; rescale */			y = (y+2.)/3.;		}	}	p.y = g->r.max.y - Dy(g->r)*y - Dot;	if(p.y < g->r.min.y)		p.y = g->r.min.y;	if(p.y > g->r.max.y-Dot)		p.y = g->r.max.y-Dot;	return p;}voiddrawdatum(Graph *g, int x, ulong prev, ulong v, ulong vmax){	int c;	Point p, q;	c = g->colindex;	p = datapoint(g, x, v, vmax);	q = datapoint(g, x, prev, vmax);	if(p.y < q.y){		draw(screen, Rect(p.x, g->r.min.y, p.x+1, p.y), cols[c][0], nil, paritypt(p.x));		draw(screen, Rect(p.x, p.y, p.x+1, q.y+Dot), cols[c][2], nil, ZP);		draw(screen, Rect(p.x, q.y+Dot, p.x+1, g->r.max.y), cols[c][1], nil, ZP);	}else{		draw(screen, Rect(p.x, g->r.min.y, p.x+1, q.y), cols[c][0], nil, paritypt(p.x));		draw(screen, Rect(p.x, q.y, p.x+1, p.y+Dot), cols[c][2], nil, ZP);		draw(screen, Rect(p.x, p.y+Dot, p.x+1, g->r.max.y), cols[c][1], nil, ZP);	}}voidredraw(Graph *g, ulong vmax){	int i, c;	c = g->colindex;	draw(screen, g->r, cols[c][0], nil, paritypt(g->r.min.x));	for(i=1; i<Dx(g->r); i++)		drawdatum(g, g->r.max.x-i, g->data[i-1], g->data[i], vmax);	drawdatum(g, g->r.min.x, g->data[i], g->data[i], vmax);	g->overflow = 0;}voidupdate1(Graph *g, ulong v, ulong vmax){	char buf[48];	int overflow;	if(g->overflow && g->overtmp!=nil)		draw(screen, g->overtmp->r, g->overtmp, nil, g->overtmp->r.min);	draw(screen, g->r, screen, nil, Pt(g->r.min.x+1, g->r.min.y));	drawdatum(g, g->r.max.x-1, g->data[0], v, vmax);	memmove(g->data+1, g->data, (g->ndata-1)*sizeof(g->data[0]));	g->data[0] = v;	g->overflow = 0;	if(logscale)		overflow = (v>10*vmax*scale);	else		overflow = (v>vmax*scale);	if(overflow && g->overtmp!=nil){		g->overflow = 1;		draw(g->overtmp, g->overtmp->r, screen, nil, g->overtmp->r.min);		sprint(buf, "%lud", v);		string(screen, g->overtmp->r.min, display->black, ZP, mediumfont, buf);	}}/* read one line of text from buffer and process integers */intreadnums(Machine *m, int n, ulong *a, int spanlines){	int i;	char *p, *ep;	if(spanlines)		ep = m->ebufp;	else		for(ep=m->bufp; ep<m->ebufp; ep++)			if(*ep == '\n')				break;	p = m->bufp;	for(i=0; i<n && p<ep; i++){		while(p<ep && !isdigit(*p) && *p!='-')			p++;		if(p == ep)			break;		a[i] = strtoul(p, &p, 10);	}	if(ep < m->ebufp)		ep++;	m->bufp = ep;	return i == n;}/* Network on fd1, mount driver on fd0 */static intfilter(int fd){	int p[2];	if(pipe(p) < 0){		fprint(2, "stats: can't pipe: %r\n");		killall("pipe");	}	switch(rfork(RFNOWAIT|RFPROC|RFFDG)) {	case -1:		sysfatal("rfork record module");	case 0:		dup(fd, 1);		close(fd);		dup(p[0], 0);		close(p[0]);		close(p[1]);		execl("/bin/aux/fcall", "fcall", nil);		fprint(2, "stats: can't exec fcall: %r\n");		killall("fcall");	default:		close(fd);		close(p[0]);	}	return p[1];	}/* * 9fs */intconnect9fs(char *addr){	char dir[256], *na;	int fd;	fprint(2, "connect9fs...");	na = netmkaddr(addr, 0, "9fs");	fprint(2, "dial %s...", na);	if((fd = dial(na, 0, dir, 0)) < 0)		return -1;	fprint(2, "dir %s...", dir);//	if(strstr(dir, "tcp"))//		fd = filter(fd);	return fd;}intold9p(int fd){	int p[2];	if(pipe(p) < 0)		return -1;	switch(rfork(RFPROC|RFFDG|RFNAMEG)) {	case -1:		return -1;	case 0:		if(fd != 1){			dup(fd, 1);			close(fd);		}		if(p[0] != 0){			dup(p[0], 0);			close(p[0]);		}		close(p[1]);		if(0){			fd = open("/sys/log/cpu", OWRITE);			if(fd != 2){				dup(fd, 2);				close(fd);			}			execl("/bin/srvold9p", "srvold9p", "-ds", nil);		} else			execl("/bin/srvold9p", "srvold9p", "-s", nil);		return -1;	default:		close(fd);		close(p[0]);	}	return p[1];	}/* * exportfs */int connectexportfs(char *addr){	char buf[ERRMAX], dir[256], *na;	int fd, n;	char *tree;	AuthInfo *ai;	tree = "/";	na = netmkaddr(addr, 0, "exportfs");	if((fd = dial(na, 0, dir, 0)) < 0)		return -1;	ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client");	if(ai == nil)		return -1;	n = write(fd, tree, strlen(tree));	if(n < 0){		close(fd);		return -1;	}	strcpy(buf, "can't read tree");	n = read(fd, buf, sizeof buf - 1);	if(n!=2 || buf[0]!='O' || buf[1]!='K'){		buf[sizeof buf - 1] = '\0';		werrstr("bad remote tree: %s\n", buf);		close(fd);		return -1;	}//	if(strstr(dir, "tcp"))//		fd = filter(fd);	if(oldsystem)		return old9p(fd);	return fd;}intreadswap(Machine *m, ulong *a){	if(strstr(m->buf, "memory\n")){		/* new /dev/swap - skip first 3 numbers */		if(!readnums(m, 7, a, 1))			return 0;		a[0] = a[3];		a[1] = a[4];		a[2] = a[5];		a[3] = a[6];		return 1;	}	return readnums(m, nelem(m->devswap), a, 0);}intinitmach(Machine *m, char *name){	int n, fd;	ulong a[MAXNUM];	char *p, mpt[256], buf[256];	p = strchr(name, '!');	if(p)		p++;	else		p = name;	m->name = estrdup(p);	m->remote = (strcmp(p, mysysname) != 0);	if(m->remote == 0)		strcpy(mpt, "");	else{		snprint(mpt, sizeof mpt, "/n/%s", p);		fd = connectexportfs(name);		if(fd < 0){			fprint(2, "can't connect to %s: %r\n", name);			return 0;		}		/* BUG? need to use amount() now? */		if(mount(fd, -1, mpt, MREPL, "") < 0){			fprint(2, "stats: mount %s on %s failed (%r); trying /n/sid\n", name, mpt);			strcpy(mpt, "/n/sid");			if(mount(fd, -1, mpt, MREPL, "") < 0){				fprint(2, "stats: mount %s on %s failed: %r\n", name, mpt);				return 0;			}		}	}	snprint(buf, sizeof buf, "%s/dev/swap", mpt);	m->swapfd = open(buf, OREAD);	if(loadbuf(m, &m->swapfd) && readswap(m, a))		memmove(m->devswap, a, sizeof m->devswap);	else		m->devswap[Maxmem] = m->devswap[Maxswap] = 100;	snprint(buf, sizeof buf, "%s/dev/sysstat", mpt);	m->statsfd = open(buf, OREAD);	if(loadbuf(m, &m->statsfd)){		for(n=0; readnums(m, nelem(m->devsysstat), a, 0); n++)			;		m->nproc = n;	}else		m->nproc = 1;	snprint(buf, sizeof buf, "%s/net/ether0/stats", mpt);	m->etherfd = open(buf, OREAD);	if(loadbuf(m, &m->etherfd) && readnums(m, nelem(m->netetherstats), a, 1))		memmove(m->netetherstats, a, sizeof m->netetherstats);	snprint(buf, sizeof buf, "%s/net/ether0/ifstats", mpt);	m->ifstatsfd = open(buf, OREAD);	if(loadbuf(m, &m->ifstatsfd)){		/* need to check that this is a wavelan interface */		if(strncmp(m->buf, "Signal: ", 8) == 0 && readnums(m, nelem(m->netetherifstats), a, 1))			memmove(m->netetherifstats, a, sizeof m->netetherifstats);	}	snprint(buf, sizeof buf, "%s/mnt/apm/battery", mpt);	m->batteryfd = open(buf, OREAD);	m->bitsybatfd = -1;	if(m->batteryfd >= 0){		if(loadbuf(m, &m->batteryfd) && readnums(m, nelem(m->batterystats), a, 0))			memmove(m->batterystats, a, sizeof(m->batterystats));	}else{		snprint(buf, sizeof buf, "%s/dev/battery", mpt);		m->bitsybatfd = open(buf, OREAD);		if(loadbuf(m, &m->bitsybatfd) && readnums(m, 1, a, 0))			memmove(m->batterystats, a, sizeof(m->batterystats));	}	return 1;}jmp_buf catchalarm;voidalarmed(void *a, char *s){	if(strcmp(s, "alarm") == 0)		notejmp(a, catchalarm, 1);	noted(NDFLT);}intneedswap(int init)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -