📄 devproc.c
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h"#include "ureg.h"enum{ Qctl, Qdir, Qfd, Qfpregs, Qkregs, Qmem, Qnote, Qnoteid, Qnotepg, Qns, Qproc, Qregs, Qsegment, Qstatus, Qtext, Qwait, Qprofile,};#define STATSIZE (2*NAMELEN+12+9*12)Dirtab procdir[] ={ "ctl", {Qctl}, 0, 0000, "fd", {Qfd}, 0, 0000, "fpregs", {Qfpregs}, sizeof(FPsave), 0000, "kregs", {Qkregs}, sizeof(Ureg), 0440, "mem", {Qmem}, 0, 0000, "note", {Qnote}, 0, 0000, "noteid", {Qnoteid}, 0, 0666, "notepg", {Qnotepg}, 0, 0000, "ns", {Qns}, 0, 0444, "proc", {Qproc}, 0, 0400, "regs", {Qregs}, sizeof(Ureg), 0000, "segment", {Qsegment}, 0, 0444, "status", {Qstatus}, STATSIZE, 0444, "text", {Qtext}, 0, 0000, "wait", {Qwait}, 0, 0400, "profile", {Qprofile}, 0, 0400,};/* Segment type from portdat.h */char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Shdata", "Map" };/* * Qids are, in path: * 4 bits of file type (qids above) * 23 bits of process slot number + 1 * in vers, * 32 bits of pid, for consistency checking * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid. */#define QSHIFT 5 /* location in qid of proc slot # */#define QID(q) (((q).path&0x0000001F)>>0)#define SLOT(q) ((((q).path&0x07FFFFFE0)>>QSHIFT)-1)#define PID(q) ((q).vers)#define NOTEID(q) ((q).vers)void procctlreq(Proc*, char*, int);int procctlmemio(Proc*, ulong, int, void*, int);Chan* proctext(Chan*, Proc*);Segment* txt2data(Proc*, Segment*);int procstopped(void*);void mntscan(Mntwalk*, Proc*);static intprocgen(Chan *c, Dirtab *tab, int, int s, Dir *dp){ Qid qid; Proc *p; Segment *q; char buf[NAMELEN]; ulong pid, path, perm, len; if(s == DEVDOTDOT){ c->qid.path = CHDIR; devdir(c, c->qid, "#p", 0, eve, 0555, dp); return 1; } if(c->qid.path == CHDIR){ if(s >= conf.nproc) return -1; p = proctab(s); pid = p->pid; if(pid == 0) return 0; sprint(buf, "%lud", pid); qid = (Qid){CHDIR|((s+1)<<QSHIFT), pid}; devdir(c, qid, buf, 0, p->user, CHDIR|0555, dp); return 1; } if(s >= nelem(procdir)) return -1; if(tab) panic("procgen"); tab = &procdir[s]; path = c->qid.path&~(CHDIR|((1<<QSHIFT)-1)); /* slot component */ p = proctab(SLOT(c->qid)); perm = tab->perm; if(perm == 0) perm = p->procmode; len = tab->length; switch(QID(c->qid)) { case Qwait: len = p->nwait * sizeof(Waitmsg); break; case Qprofile: q = p->seg[TSEG]; if(q && q->profile) { len = (q->top-q->base)>>LRESPROF; len *= sizeof(*q->profile); } break; } qid = (Qid){path|tab->qid.path, c->qid.vers}; devdir(c, qid, tab->name, len, p->user, perm, dp); return 1;}static voidprocinit(void){ if(conf.nproc >= (1<<(16-QSHIFT))-1) print("warning: too many procs for devproc\n");}static Chan*procattach(char *spec){ return devattach('p', spec);}static intprocwalk(Chan *c, char *name){ return devwalk(c, name, 0, 0, procgen);}static voidprocstat(Chan *c, char *db){ devstat(c, db, 0, 0, procgen);}static Chan*procopen(Chan *c, int omode){ Proc *p; Pgrp *pg; Chan *tc; int pid; if(c->qid.path & CHDIR) return devopen(c, omode, 0, 0, procgen); p = proctab(SLOT(c->qid)); qlock(&p->debug); if(waserror()){ qunlock(&p->debug); nexterror(); } pid = PID(c->qid); if(p->pid != pid) error(Eprocdied); omode = openmode(omode); switch(QID(c->qid)){ case Qtext: if(omode != OREAD) error(Eperm); tc = proctext(c, p); tc->offset = 0; qunlock(&p->debug); poperror(); return tc; case Qproc: case Qkregs: case Qsegment: case Qprofile: case Qfd: if(omode != OREAD) error(Eperm); break; case Qctl: case Qnote: case Qnoteid: case Qmem: case Qstatus: case Qwait: case Qregs: case Qfpregs: break; case Qns: if(omode != OREAD) error(Eperm); c->aux = malloc(sizeof(Mntwalk)); break; case Qnotepg: pg = p->pgrp; if(pg == nil) error(Eprocdied); if(omode!=OWRITE || pg->pgrpid == 1) error(Eperm); c->pgrpid.path = pg->pgrpid+1; c->pgrpid.vers = p->noteid; break; default: pprint("procopen %lux\n", c->qid); error(Egreg); } /* Affix pid to qid */ if(p->state != Dead) c->qid.vers = p->pid; /* make sure the process slot didn't get reallocated while we were playing */ coherence(); if(p->pid != pid) error(Eprocdied); tc = devopen(c, omode, 0, 0, procgen); qunlock(&p->debug); poperror(); return tc;}static voidprocwstat(Chan *c, char *db){ Proc *p; Dir d; if(c->qid.path&CHDIR) error(Eperm); p = proctab(SLOT(c->qid)); if(waserror()){ qunlock(&p->debug); nexterror(); } qlock(&p->debug); if(p->pid != PID(c->qid)) error(Eprocdied); if(strcmp(up->user, p->user) != 0 && strcmp(up->user, eve) != 0) error(Eperm); convM2D(db, &d); if(strcmp(d.uid, p->user) != 0){ if(strcmp(up->user, eve) != 0) error(Eperm); else { strncpy(p->user, d.uid, sizeof(p->user)); p->user[sizeof(p->user)-1] = 0; } } p->procmode = d.mode&0777; poperror(); qunlock(&p->debug);}static intprocfds(Proc *p, char *va, int count, long offset){ Fgrp *f; Chan *c; int n, i; qlock(&p->debug); f = p->fgrp; if(f == nil){ qunlock(&p->debug); return 0; } lock(f); if(waserror()){ unlock(f); qunlock(&p->debug); nexterror(); } n = readstr(0, va, count, p->dot->name->s); n += snprint(va+n, count-n, "\n"); for(i = 0; i <= f->maxfd; i++) { c = f->fd[i]; if(c == nil) continue; n += snprint(va+n, count-n, "%3d %.2s %C %4ld %.8lux.%.8lud %8lld ", i, &"r w rw"[(c->mode&3)<<1], devtab[c->type]->dc, c->dev, c->qid.path, c->qid.vers, c->offset); n += readstr(0, va+n, count-n, c->name->s); n += snprint(va+n, count-n, "\n"); if(offset > 0) { offset -= n; if(offset < 0) { memmove(va, va+n+offset, -offset); n = -offset; } else n = 0; } } unlock(f); qunlock(&p->debug); poperror(); return n;}static voidprocclose(Chan * c){ if(QID(c->qid) == Qns && c->aux != 0) free(c->aux);}static voidint2flag(int flag, char *s){ if(flag == 0){ *s = '\0'; return; } *s++ = '-'; if(flag & MAFTER) *s++ = 'a'; if(flag & MBEFORE) *s++ = 'b'; if(flag & MCREATE) *s++ = 'c'; if(flag & MCACHE) *s++ = 'C'; *s = '\0';}static longprocread(Chan *c, void *va, long n, vlong off){ long l; Proc *p; Waitq *wq; Ureg kur; uchar *rptr; Mntwalk *mw; Segment *sg, *s; char *a = va, *sps; int i, j, rsize, pid; char statbuf[NSEG*32], *srv, flag[10]; ulong offset = off; if(c->qid.path & CHDIR) return devdirread(c, a, n, 0, 0, procgen); p = proctab(SLOT(c->qid)); if(p->pid != PID(c->qid)) error(Eprocdied); switch(QID(c->qid)){ case Qmem: if(offset < KZERO || (offset >= USTKTOP-USTKSIZE && offset < USTKTOP)) return procctlmemio(p, offset, n, va, 1); /* Protect crypt key memory */ if(offset+n >= palloc.cmembase && offset < palloc.cmemtop) error(Eperm); /* validate physical kernel addresses */ if(offset < (ulong)end) { if(offset+n > (ulong)end) n = (ulong)end - offset; memmove(a, (char*)offset, n); return n; } if(offset >= conf.base0 && offset < conf.npage0){ if(offset+n > conf.npage0) n = conf.npage0 - offset; memmove(a, (char*)offset, n); return n; } if(offset >= conf.base1 && offset < conf.npage1){ if(offset+n > conf.npage1) n = conf.npage1 - offset; memmove(a, (char*)offset, n); return n; } error(Ebadarg); case Qprofile: s = p->seg[TSEG]; if(s == 0 || s->profile == 0) error("profile is off"); i = (s->top-s->base)>>LRESPROF; i *= sizeof(*s->profile); if(offset >= i) return 0; if(offset+n > i) n = i - offset; memmove(a, ((char*)s->profile)+offset, n); return n; case Qnote: qlock(&p->debug); if(waserror()){ qunlock(&p->debug); nexterror(); } if(p->pid != PID(c->qid)) error(Eprocdied); if(n < ERRLEN) error(Etoosmall); if(p->nnote == 0) n = 0; else { memmove(va, p->note[0].msg, ERRLEN); p->nnote--; memmove(p->note, p->note+1, p->nnote*sizeof(Note)); n = ERRLEN; } if(p->nnote == 0) p->notepending = 0; poperror(); qunlock(&p->debug); return n; case Qproc: if(offset >= sizeof(Proc)) return 0; if(offset+n > sizeof(Proc)) n = sizeof(Proc) - offset; memmove(a, ((char*)p)+offset, n); return n; case Qregs: rptr = (uchar*)p->dbgreg; rsize = sizeof(Ureg); goto regread; case Qkregs: memset(&kur, 0, sizeof(Ureg)); setkernur(&kur, p); rptr = (uchar*)&kur; rsize = sizeof(Ureg); goto regread; case Qfpregs: rptr = (uchar*)&p->fpsave; rsize = sizeof(FPsave); regread: if(rptr == 0) error(Enoreg); if(offset >= rsize) return 0; if(offset+n > rsize) n = rsize - offset; memmove(a, rptr+offset, n); return n; case Qstatus: if(offset >= STATSIZE) return 0; if(offset+n > STATSIZE) n = STATSIZE - offset; sps = p->psstate; if(sps == 0) sps = statename[p->state]; memset(statbuf, ' ', sizeof statbuf); memmove(statbuf+0*NAMELEN, p->text, strlen(p->text)); memmove(statbuf+1*NAMELEN, p->user, strlen(p->user)); memmove(statbuf+2*NAMELEN, sps, strlen(sps)); j = 2*NAMELEN + 12; for(i = 0; i < 6; i++) { l = p->time[i]; if(i == TReal) l = MACHP(0)->ticks - l; l = TK2MS(l); readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, l, NUMSIZE); } /* ignore stack, which is mostly non-existent */ l = 0; for(i=1; i<NSEG; i++){ s = p->seg[i]; if(s) l += s->top - s->base; } readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, l>>10, NUMSIZE); readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE); readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE); memmove(a, statbuf+offset, n); return n; case Qsegment: j = 0; for(i = 0; i < NSEG; i++) { sg = p->seg[i]; if(sg == 0) continue; j += sprint(statbuf+j, "%-6s %c%c %.8lux %.8lux %4ld\n", sname[sg->type&SG_TYPE], sg->type&SG_RONLY ? 'R' : ' ', sg->profile ? 'P' : ' ', sg->base, sg->top, sg->ref); } if(offset >= j) return 0; if(offset+n > j) n = j-offset; if(n == 0 && offset == 0) exhausted("segments"); memmove(a, &statbuf[offset], n); return n; case Qwait: if(n < sizeof(Waitmsg)) error(Etoosmall); if(!canqlock(&p->qwaitr)) error(Einuse);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -