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

📄 rdbfs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
/* * Remote debugging file system */#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include <bio.h>#include <thread.h>#include <9p.h>int dbg = 0;#define DBG	if(dbg)fprintenum {	NHASH = 4096,	Readlen = 4,	Pagequantum = 1024,};/* caching memory pages: a lot of space to avoid serial communications */Lock pglock;typedef struct	Page	Page;struct Page {	/* cached memory contents */	Page *link;	ulong len;	ulong addr;	int count;	uchar val[Readlen];};Page *pgtab[NHASH];Page *freelist;/* called with pglock locked */Page*newpg(void){	int i;	Page *p, *q;	if(freelist == nil){		p = malloc(sizeof(Page)*Pagequantum);		if(p == nil)			sysfatal("out of memory");		for(i=0, q=p; i<Pagequantum-1; i++, q++)			q->link = q+1;		q->link = nil;		freelist = p;	}	p = freelist;	freelist = freelist->link;	return p;}#define PHIINV 0.61803398874989484820uintahash(ulong addr){	return (uint)floor(NHASH*fmod(addr*PHIINV, 1.0));}intlookup(ulong addr, uchar *val, ulong count){	Page *p;	lock(&pglock);	for(p=pgtab[ahash(addr)]; p; p=p->link){		if(p->addr == addr && p->count == count){			memmove(val, p->val, count);			unlock(&pglock);			return 1;		}	}	unlock(&pglock);	return 0;}voidinsert(ulong addr, uchar *val, int count){	Page *p;	uint h;	lock(&pglock);	p = newpg();	p->addr = addr;	p->count = count;	memmove(p->val, val, count);	h = ahash(addr);	p->link = pgtab[h];	p->len = pgtab[h] ? pgtab[h]->len+1 : 1;	pgtab[h] = p;	unlock(&pglock);}voidflushcache(void){	int i;	Page *p;	lock(&pglock);	for(i=0; i<NHASH; i++){		if(p=pgtab[i]){			for(;p->link; p=p->link)				;			p->link = freelist;			freelist = p;		}		pgtab[i] = nil;	}	unlock(&pglock);}enum{	Xctl	= 1,	Xfpregs,	Xkregs,	Xmem,	Xproc,	Xregs,	Xtext,	Xstatus,};int	textfd;int	rfd;Biobuf	rfb;char*	portname = "/dev/eia0";char*	textfile = "/386/9pc";char*	procname = "1";Channel* rchan;voidusage(void){	fprint(2, "usage: rdbfs [-p procnum] [-t textfile] [serialport]\n");	exits("usage");}voidnoalarm(void*, char *msg){	if(strstr(msg, "alarm"))		noted(NCONT);	noted(NDFLT);}/* * 	send and receive responses on the serial line */voideiaread(void*){	Req *r;	char *p;	uchar *data;	char err[ERRMAX];	char buf[1000];	int i, tries;	notify(noalarm);	while(r = recvp(rchan)){		DBG(2, "got %F: here goes...", &r->ifcall);		if(r->ifcall.count > Readlen)			r->ifcall.count = Readlen;		r->ofcall.count = r->ifcall.count;		if(r->type == Tread && lookup(r->ifcall.offset, (uchar*)r->ofcall.data, r->ofcall.count)){			respond(r, nil);			continue;		}		for(tries=0; tries<5; tries++){			if(r->type == Twrite){				DBG(2, "w%.8lux %.8lux...", (ulong)r->ifcall.offset, *(ulong*)r->ifcall.data);				fprint(rfd, "w%.8lux %.8lux\n", (ulong)r->ifcall.offset, *(ulong*)r->ifcall.data);			}else if(r->type == Tread){				DBG(2, "r%.8lux...", (ulong)r->ifcall.offset);				fprint(rfd, "r%.8lux\n", (ulong)r->ifcall.offset);			}else{				respond(r, "oops");				break;			}			for(;;){				werrstr("");				alarm(500);				p=Brdline(&rfb, '\n');				alarm(0);				if(p == nil){					rerrstr(err, sizeof err);					DBG(2, "error %s\n", err);					if(strstr(err, "alarm") || strstr(err, "interrupted"))						break;					if(Blinelen(&rfb) == 0) // true eof						sysfatal("eof on serial line?");					Bread(&rfb, buf, Blinelen(&rfb)<sizeof buf ? Blinelen(&rfb) : sizeof buf);					continue;				}				p[Blinelen(&rfb)-1] = 0;				if(p[0] == '\r')					p++;				DBG(2, "serial %s\n", p);				if(p[0] == 'R'){					if(strtoul(p+1, 0, 16) == (ulong)r->ifcall.offset){						/* we know that data can handle Readlen bytes */						data = (uchar*)r->ofcall.data;						for(i=0; i<r->ifcall.count; i++)							data[i] = strtol(p+1+8+1+3*i, 0, 16);						insert(r->ifcall.offset, data, r->ifcall.count);						respond(r, nil);						goto Break2;					}else						DBG(2, "%.8lux ≠ %.8lux\n", strtoul(p+1, 0, 16), (ulong)r->ifcall.offset);				}else if(p[0] == 'W'){					respond(r, nil);					goto Break2;				}else{					DBG(2, "unknown message\n");				}			}		}	Break2:;	}}voidattachremote(char* name){	int fd;	char buf[128];	print("attach %s\n", name);	rfd = open(name, ORDWR);	if(rfd < 0)		sysfatal("can't open remote %s", name);	sprint(buf, "%sctl", name);	fd = open(buf, OWRITE);	if(fd < 0)		sysfatal("can't set baud rate on %s", buf);	write(fd, "B9600", 6);	close(fd);	Binit(&rfb, rfd, OREAD);}voidfsopen(Req *r){	char buf[ERRMAX];	switch((uintptr)r->fid->file->aux){	case Xtext:		close(textfd);		textfd = open(textfile, OREAD);		if(textfd < 0) {			snprint(buf, sizeof buf, "text: %r");			respond(r, buf);			return;		}		break;	}			respond(r, nil);}voidfsread(Req *r){	int i, n;	char buf[512];	switch((uintptr)r->fid->file->aux) {	case Xfpregs:	case Xproc:	case Xregs:		respond(r, "Egreg");		break;	case Xkregs:	case Xmem:		if(sendp(rchan, r) != 1){			snprint(buf, sizeof buf, "rdbfs sendp: %r");			respond(r, buf);			return;		}		break;	case Xtext:		n = pread(textfd, r->ofcall.data, r->ifcall.count, r->ifcall.offset);		if(n < 0) {			rerrstr(buf, sizeof buf);			respond(r, buf);			break;		}		r->ofcall.count = n;		respond(r, nil);		break;	case Xstatus:		n = sprint(buf, "%-28s%-28s%-28s", "remote", "system", "New");		for(i = 0; i < 9; i++)			n += sprint(buf+n, "%-12d", 0);		readstr(r, buf);		respond(r, nil);		break;	default:		respond(r, "unknown read");	}}voidfswrite(Req *r){	char buf[ERRMAX];	switch((uintptr)r->fid->file->aux) {	case Xctl:		if(strncmp(r->ifcall.data, "kill", 4) == 0 ||		   strncmp(r->ifcall.data, "exit", 4) == 0) {			respond(r, nil);			postnote(PNGROUP, getpid(), "umount");			exits(nil);		}else if(strncmp(r->ifcall.data, "refresh", 7) == 0){			flushcache();			respond(r, nil);		}else if(strncmp(r->ifcall.data, "hashstats", 9) == 0){			int i;			lock(&pglock);			for(i=0; i<NHASH; i++)				if(pgtab[i])					print("%lud ", pgtab[i]->len);			print("\n");			unlock(&pglock);			respond(r, nil);		}else			respond(r, "permission denied");		break;	case Xkregs:	case Xmem:		if(sendp(rchan, r) != 1) {			snprint(buf, sizeof buf, "rdbfs sendp: %r");			respond(r, buf);			return;		}		break;	default:		respond(r, "Egreg");		break;	}}struct {	char *s;	int id;	int mode;} tab[] = {	"ctl",		Xctl,		0222,	"fpregs",	Xfpregs,	0666,	"kregs",	Xkregs,		0666,	"mem",		Xmem,		0666,	"proc",		Xproc,		0444,	"regs",		Xregs,		0666,	"text",		Xtext,		0444,	"status",	Xstatus,	0444,};voidkillall(Srv*){	postnote(PNGROUP, getpid(), "kill");}Srv fs = {.open=	fsopen,.read=	fsread,.write=	fswrite,.end=	killall,};voidthreadmain(int argc, char **argv){	int i, p[2];	File *dir;	rfork(RFNOTEG);	ARGBEGIN{	case 'D':		chatty9p++;		break;	case 'd':		dbg = 1;		break;	case 'p':		procname = EARGF(usage());		break;	case 't':		textfile = EARGF(usage());		break;	default:		usage();	}ARGEND;	switch(argc){	case 0:		break;	case 1:		portname = argv[0];		break;	default:		usage();	}	rchan = chancreate(sizeof(Req*), 10);	attachremote(portname);	if(pipe(p) < 0)		sysfatal("pipe: %r");	fmtinstall('F', fcallfmt);	proccreate(eiaread, nil, 8192);	fs.tree = alloctree("rdbfs", "rdbfs", DMDIR|0555, nil);	dir = createfile(fs.tree->root, procname, "rdbfs", DMDIR|0555, 0);	for(i=0; i<nelem(tab); i++)		closefile(createfile(dir, tab[i].s, "rdbfs", tab[i].mode, (void*)tab[i].id));	closefile(dir);	threadpostmountsrv(&fs, nil, "/proc", MBEFORE);	exits(0);}

⌨️ 快捷键说明

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