📄 rdbfs.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 + -