📄 devproc.c
字号:
qlock(&p->debug); if(waserror()){ qunlock(&p->debug); nexterror(); } if(p->pid != PID(c->qid)) error(Eprocdied); if(n < 1) /* must accept at least the '\0' */ error(Etoosmall); if(p->nnote == 0) n = 0; else { m = strlen(p->note[0].msg) + 1; if(m > n) m = n; memmove(va, p->note[0].msg, m); ((char*)va)[m-1] = '\0'; p->nnote--; memmove(p->note, p->note+1, p->nnote*sizeof(Note)); n = m; } 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*KNAMELEN, p->text, strlen(p->text)); memmove(statbuf+1*KNAMELEN, p->user, strlen(p->user)); memmove(statbuf+2*KNAMELEN, sps, strlen(sps)); j = 2*KNAMELEN + 12; for(i = 0; i < 6; i++) { l = p->time[i]; if(i == TReal) l = msec() - 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(!canqlock(&p->qwaitr)) error(Einuse); if(waserror()) { qunlock(&p->qwaitr); nexterror(); } lock(&p->exl); if(up == p && p->nchild == 0 && p->waitq == 0) { unlock(&p->exl); error(Enochild); } pid = p->pid; while(p->waitq == 0) { unlock(&p->exl); sleep(&p->waitr, haswaitq, p); if(p->pid != pid) error(Eprocdied); lock(&p->exl); } wq = p->waitq; p->waitq = wq->next; p->nwait--; unlock(&p->exl); qunlock(&p->qwaitr); poperror(); n = snprint(a, n, "%d %lud %lud %lud %q", wq->w.pid, wq->w.time[TUser], wq->w.time[TSys], wq->w.time[TReal], wq->w.msg); free(wq); return n; case Qns: qlock(&p->debug); if(waserror()){ qunlock(&p->debug); nexterror(); } if(p->pgrp == nil || p->pid != PID(c->qid)) error(Eprocdied); mw = c->aux; if(mw->cddone){ qunlock(&p->debug); poperror(); return 0; } mntscan(mw, p); if(mw->mh == 0){ mw->cddone = 1; i = snprint(a, n, "cd %s\n", p->dot->path->s); qunlock(&p->debug); poperror(); return i; } int2flag(mw->cm->mflag, flag); if(strcmp(mw->cm->to->path->s, "#M") == 0){ srv = srvname(mw->cm->to->mchan); i = snprint(a, n, "mount %s %s %s %s\n", flag, srv==nil? mw->cm->to->mchan->path->s : srv, mw->mh->from->path->s, mw->cm->spec? mw->cm->spec : ""); free(srv); }else i = snprint(a, n, "bind %s %s %s\n", flag, mw->cm->to->path->s, mw->mh->from->path->s); qunlock(&p->debug); poperror(); return i; case Qnoteid: return readnum(offset, va, n, p->noteid, NUMSIZE); case Qfd: return procfds(p, va, n, offset); } error(Egreg); return 0; /* not reached */}voidmntscan(Mntwalk *mw, Proc *p){ Pgrp *pg; Mount *t; Mhead *f; int nxt, i; ulong last, bestmid; pg = p->pgrp; rlock(&pg->ns); nxt = 0; bestmid = ~0; last = 0; if(mw->mh) last = mw->cm->mountid; for(i = 0; i < MNTHASH; i++) { for(f = pg->mnthash[i]; f; f = f->hash) { for(t = f->mount; t; t = t->next) { if(mw->mh == 0 || (t->mountid > last && t->mountid < bestmid)) { mw->cm = t; mw->mh = f; bestmid = mw->cm->mountid; nxt = 1; } } } } if(nxt == 0) mw->mh = 0; runlock(&pg->ns);}static longprocwrite(Chan *c, void *va, long n, vlong off){ int id, m; Proc *p, *t, *et; char *a, *arg, buf[ERRMAX]; ulong offset = off; a = va; if(c->qid.type & QTDIR) error(Eisdir); p = proctab(SLOT(c->qid)); /* Use the remembered noteid in the channel rather * than the process pgrpid */ if(QID(c->qid) == Qnotepg) { pgrpnote(NOTEID(c->pgrpid), va, n, NUser); return n; } qlock(&p->debug); if(waserror()){ qunlock(&p->debug); nexterror(); } if(p->pid != PID(c->qid)) error(Eprocdied); switch(QID(c->qid)){ case Qargs: if(n == 0) error(Eshort); if(n >= ERRMAX) error(Etoobig); arg = malloc(n+1); if(arg == nil) error(Enomem); memmove(arg, va, n); m = n; if(arg[m-1] != 0) arg[m++] = 0; free(p->args); p->nargs = m; p->args = arg; p->setargs = 1; break; case Qmem: if(p->state != Stopped) error(Ebadctl); n = procctlmemio(p, offset, n, va, 0); break; case Qregs: if(offset >= sizeof(Ureg)) n = 0; else if(offset+n > sizeof(Ureg)) n = sizeof(Ureg) - offset; if(p->dbgreg == 0) error(Enoreg); setregisters(p->dbgreg, (char*)(p->dbgreg)+offset, va, n); break; case Qfpregs: if(offset >= sizeof(FPsave)) n = 0; else if(offset+n > sizeof(FPsave)) n = sizeof(FPsave) - offset; memmove((uchar*)&p->fpsave+offset, va, n); break; case Qctl: procctlreq(p, va, n); break; case Qnote: if(p->kp) error(Eperm); if(n >= ERRMAX-1) error(Etoobig); memmove(buf, va, n); buf[n] = 0; if(!postnote(p, 0, buf, NUser)) error("note not posted"); break; case Qnoteid: id = atoi(a); if(id == p->pid) { p->noteid = id; break; } t = proctab(0); for(et = t+conf.nproc; t < et; t++) { if(t->state == Dead) continue; if(id == t->noteid) { if(strcmp(p->user, t->user) != 0) error(Eperm); p->noteid = id; break; } } if(p->noteid != id) error(Ebadarg); break; default: pprint("unknown qid in procwrite\n"); error(Egreg); } poperror(); qunlock(&p->debug); return n;}Dev procdevtab = { 'p', "proc", devreset, procinit, devshutdown, procattach, procwalk, procstat, procopen, devcreate, procclose, procread, devbread, procwrite, devbwrite, devremove, procwstat,};Chan*proctext(Chan *c, Proc *p){ Chan *tc; Image *i; Segment *s; s = p->seg[TSEG]; if(s == 0) error(Enonexist); if(p->state==Dead) error(Eprocdied); lock(&s->ref.lk); i = s->image; if(i == 0) { unlock(&s->ref.lk); error(Eprocdied); } unlock(&s->ref.lk); lock(&i->ref.lk); if(waserror()) { unlock(&i->ref.lk); nexterror(); } tc = i->c; if(tc == 0) error(Eprocdied); if(incref(&tc->ref) == 1 || (tc->flag&COPEN) == 0 || tc->mode!=OREAD) { cclose(tc); error(Eprocdied); } if(p->pid != PID(c->qid)) error(Eprocdied); unlock(&i->ref.lk); poperror(); return tc;}voidprocstopwait(Proc *p, int ctl){ int pid; if(p->pdbg) error(Einuse); if(procstopped(p) || p->state == Broken) return; if(ctl != 0) p->procctl = ctl; p->pdbg = up; pid = p->pid; qunlock(&p->debug); up->psstate = "Stopwait"; if(waserror()) { p->pdbg = 0; qlock(&p->debug); nexterror(); } sleep(&up->sleep, procstopped, p); poperror(); qlock(&p->debug); if(p->pid != pid) error(Eprocdied);}static voidprocctlcloseone(Proc *p, Fgrp *f, int fd){ Chan *c; c = f->fd[fd]; if(c == nil) return; f->fd[fd] = nil; unlock(&f->ref.lk); qunlock(&p->debug); cclose(c); qlock(&p->debug); lock(&f->ref.lk);}voidprocctlclosefiles(Proc *p, int all, int fd){ int i; Fgrp *f; f = p->fgrp; if(f == nil) error(Eprocdied); lock(&f->ref.lk); f->ref.ref++; if(all) for(i = 0; i < f->maxfd; i++) procctlcloseone(p, f, i); else procctlcloseone(p, f, fd); unlock(&f->ref.lk); closefgrp(f);}voidprocctlreq(Proc *p, char *va, int n){ Segment *s; int npc, pri; Cmdbuf *cb; Cmdtab *ct; if(p->kp) /* no ctl requests to kprocs */ error(Eperm); cb = parsecmd(va, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, proccmd, nelem(proccmd)); switch(ct->index){ case CMclose: procctlclosefiles(p, 0, atoi(cb->f[1])); break; case CMclosefiles: procctlclosefiles(p, 1, 0); break; case CMhang: p->hang = 1; break; case CMkill: switch(p->state) { case Broken: unbreak(p); break; case Stopped: p->procctl = Proc_exitme; postnote(p, 0, "sys: killed", NExit); ready(p); break; default: p->procctl = Proc_exitme; postnote(p, 0, "sys: killed", NExit); } break; case CMnohang: p->hang = 0; break; case CMnoswap: p->noswap = 1; break; case CMpri: pri = atoi(cb->f[1]); if(pri > PriNormal && !iseve()) error(Eperm); procpriority(p, pri, 0); break; case CMfixedpri: pri = atoi(cb->f[1]); if(pri > PriNormal && !iseve()) error(Eperm); procpriority(p, pri, 1); break; case CMprivate: p->privatemem = 1; break; case CMprofile: s = p->seg[TSEG]; if(s == 0 || (s->type&SG_TYPE) != SG_TEXT) error(Ebadctl); if(s->profile != 0) free(s->profile); npc = (s->top-s->base)>>LRESPROF; s->profile = malloc(npc*sizeof(*s->profile)); if(s->profile == 0) error(Enomem); break; case CMstart: if(p->state != Stopped) error(Ebadctl); ready(p); break; case CMstartstop: if(p->state != Stopped) error(Ebadctl); p->procctl = Proc_traceme; ready(p); procstopwait(p, Proc_traceme); break; case CMstartsyscall: if(p->state != Stopped) error(Ebadctl); p->procctl = Proc_tracesyscall; ready(p); procstopwait(p, Proc_tracesyscall); break; case CMstop: procstopwait(p, Proc_stopme); break; case CMwaitstop: procstopwait(p, 0); break; case CMwired: procwired(p, atoi(cb->f[1])); break; case CMtrace: switch(cb->nf){ case 1: p->trace ^= 1; break; case 2: p->trace = (atoi(cb->f[1]) != 0); break; default: error("args"); } break; } poperror(); free(cb);}intprocstopped(void *a){ Proc *p = a; return p->state == Stopped;}intprocctlmemio(Proc *p, ulong offset, int n, void *va, int read){ KMap *k; Pte *pte; Page *pg; Segment *s; ulong soff, l; char *a = va, *b; for(;;) { s = seg(p, offset, 1); if(s == 0) error(Ebadarg); if(offset+n >= s->top) n = s->top-offset; if(!read && (s->type&SG_TYPE) == SG_TEXT) s = txt2data(p, s); s->steal++; soff = offset-s->base; if(waserror()) { s->steal--; nexterror(); } if(fixfault(s, offset, read, 0) == 0) break; poperror(); s->steal--; } poperror(); pte = s->map[soff/PTEMAPMEM]; if(pte == 0) panic("procctlmemio"); pg = pte->pages[(soff&(PTEMAPMEM-1))/BY2PG]; if(pagedout(pg)) panic("procctlmemio1"); l = BY2PG - (offset&(BY2PG-1)); if(n > l) n = l; k = kmap(pg); if(waserror()) { s->steal--; kunmap(k); nexterror(); } b = (char*)VA(k); b += offset&(BY2PG-1); if(read == 1) memmove(a, b, n); /* This can fault */ else memmove(b, a, n); kunmap(k); poperror(); /* Ensure the process sees text page changes */ s->steal--; if(read == 0) p->newtlb = 1; return n;}Segment*txt2data(Proc *p, Segment *s){ int i; Segment *ps; ps = newseg(SG_DATA, s->base, s->size); ps->image = s->image; incref(&ps->image->ref); ps->fstart = s->fstart; ps->flen = s->flen; ps->flushme = 1; qlock(&p->seglock); for(i = 0; i < NSEG; i++) if(p->seg[i] == s) break; if(p->seg[i] != s) panic("segment gone"); qunlock(&s->lk); putseg(s); qlock(&ps->lk); p->seg[i] = ps; qunlock(&p->seglock); return ps;}Segment*data2txt(Segment *s){ Segment *ps; ps = newseg(SG_TEXT, s->base, s->size); ps->image = s->image; incref(&ps->image->ref); ps->fstart = s->fstart; ps->flen = s->flen; ps->flushme = 1; return ps;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -