?? readproc.c
字號:
if(unlikely(num >= sizeof P->cmd)) num = sizeof P->cmd - 1; memcpy(P->cmd, S, num); P->cmd[num] = '\0'; S = tmp + 2; // skip ") " num = sscanf(S, "%c " "%d %d %d %d %d " "%lu %lu %lu %lu %lu " "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime */ "%ld %ld " "%d " "%ld " "%Lu " /* start_time */ "%lu " "%ld " "%lu %"KLF"u %"KLF"u %"KLF"u %"KLF"u %"KLF"u " "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */ "%"KLF"u %*lu %*lu " "%d %d " "%lu %lu", &P->state, &P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid, &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt, &P->utime, &P->stime, &P->cutime, &P->cstime, &P->priority, &P->nice, &P->nlwp, &P->alarm, &P->start_time, &P->vsize, &P->rss, &P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, &P->kstk_eip,/* P->signal, P->blocked, P->sigignore, P->sigcatch, */ /* can't use */ &P->wchan, /* &P->nswap, &P->cnswap, */ /* nswap and cnswap dead for 2.4.xx and up *//* -- Linux 2.0.35 ends here -- */ &P->exit_signal, &P->processor, /* 2.2.1 ends with "exit_signal" *//* -- Linux 2.2.8 to 2.5.17 end here -- */ &P->rtprio, &P->sched /* both added to 2.5.18 */ ); if(!P->nlwp){ P->nlwp = 1; }LEAVE(0x160);}/////////////////////////////////////////////////////////////////////////static void statm2proc(const char* s, proc_t *restrict P) { int num; num = sscanf(s, "%ld %ld %ld %ld %ld %ld %ld", &P->size, &P->resident, &P->share, &P->trs, &P->lrs, &P->drs, &P->dt);/* fprintf(stderr, "statm2proc converted %d fields.\n",num); */}static int file2str(const char *directory, const char *what, char *ret, int cap) { static char filename[80]; int fd, num_read; sprintf(filename, "%s/%s", directory, what); fd = open(filename, O_RDONLY, 0); if(unlikely(fd==-1)) return -1; num_read = read(fd, ret, cap - 1); close(fd); if(unlikely(num_read<=0)) return -1; ret[num_read] = '\0'; return num_read;}static char** file2strvec(const char* directory, const char* what) { char buf[2048]; /* read buf bytes at a time */ char *p, *rbuf = 0, *endbuf, **q, **ret; int fd, tot = 0, n, c, end_of_file = 0; int align; sprintf(buf, "%s/%s", directory, what); fd = open(buf, O_RDONLY, 0); if(fd==-1) return NULL; /* read whole file into a memory buffer, allocating as we go */ while ((n = read(fd, buf, sizeof buf - 1)) > 0) { if (n < (int)(sizeof buf - 1)) end_of_file = 1; if (n == 0 && rbuf == 0) return NULL; /* process died between our open and read */ if (n < 0) { if (rbuf) free(rbuf); return NULL; /* read error */ } if (end_of_file && buf[n-1]) /* last read char not null */ buf[n++] = '\0'; /* so append null-terminator */ rbuf = xrealloc(rbuf, tot + n); /* allocate more memory */ memcpy(rbuf + tot, buf, n); /* copy buffer into it */ tot += n; /* increment total byte ctr */ if (end_of_file) break; } close(fd); if (n <= 0 && !end_of_file) { if (rbuf) free(rbuf); return NULL; /* read error */ } endbuf = rbuf + tot; /* count space for pointers */ align = (sizeof(char*)-1) - ((tot + sizeof(char*)-1) & (sizeof(char*)-1)); for (c = 0, p = rbuf; p < endbuf; p++) if (!*p) c += sizeof(char*); c += sizeof(char*); /* one extra for NULL term */ rbuf = xrealloc(rbuf, tot + c + align); /* make room for ptrs AT END */ endbuf = rbuf + tot; /* addr just past data buf */ q = ret = (char**) (endbuf+align); /* ==> free(*ret) to dealloc */ *q++ = p = rbuf; /* point ptrs to the strings */ endbuf--; /* do not traverse final NUL */ while (++p < endbuf) if (!*p) /* NUL char implies that */ *q++ = p+1; /* next string -> next char */ *q = 0; /* null ptr list terminator */ return ret;}// warning: interface may changeint read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){ char name[32]; int fd; unsigned n = 0; dst[0] = '\0'; snprintf(name, sizeof name, "/proc/%u/cmdline", pid); fd = open(name, O_RDONLY); if(fd==-1) return 0; for(;;){ ssize_t r = read(fd,dst+n,sz-n); if(r==-1){ if(errno==EINTR) continue; break; } n += r; if(n==sz) break; // filled the buffer if(r==0) break; // EOF } close(fd); if(n){ int i; if(n==sz) n--; dst[n] = '\0'; i=n; while(i--){ int c = dst[i]; if(c<' ' || c>'~') dst[i]=' '; } } return n;}/* These are some nice GNU C expression subscope "inline" functions. * The can be used with arbitrary types and evaluate their arguments * exactly once. *//* Test if item X of type T is present in the 0 terminated list L */# define XinL(T, X, L) ( { \ T x = (X), *l = (L); \ while (*l && *l != x) l++; \ *l == x; \ } )/* Test if item X of type T is present in the list L of length N */# define XinLN(T, X, L, N) ( { \ T x = (X), *l = (L); \ int i = 0, n = (N); \ while (i < n && l[i] != x) i++; \ i < n && l[i] == x; \ } )//////////////////////////////////////////////////////////////////////////////////// This reads process info from /proc in the traditional way, for one process.// The pid (tgid? tid?) is already in p, and a path to it in path, with some// room to spare.static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict const p) { static struct stat sb; // stat() buffer static char sbuf[1024]; // buffer for stat,statm char *restrict const path = PT->path; unsigned flags = PT->flags; if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */ goto next_proc; if ((flags & PROC_UID) && !XinLN(uid_t, sb.st_uid, PT->uids, PT->nuid)) goto next_proc; /* not one of the requested uids */ p->euid = sb.st_uid; /* need a way to get real uid */ p->egid = sb.st_gid; /* need a way to get real gid */ if (flags & PROC_FILLSTAT) { /* read, parse /proc/#/stat */ if (unlikely( file2str(path, "stat", sbuf, sizeof sbuf) == -1 )) goto next_proc; /* error reading /proc/#/stat */ stat2proc(sbuf, p); /* parse /proc/#/stat */ } if (unlikely(flags & PROC_FILLMEM)) { /* read, parse /proc/#/statm */ if (likely( file2str(path, "statm", sbuf, sizeof sbuf) != -1 )) statm2proc(sbuf, p); /* ignore statm errors here */ } /* statm fields just zero */ if (flags & PROC_FILLSTATUS) { /* read, parse /proc/#/status */ if (likely( file2str(path, "status", sbuf, sizeof sbuf) != -1 )){ status2proc(sbuf, p, 1); } } // if multithreaded, some values are crap if(p->nlwp > 1){ p->wchan = (KLONG)~0ull; } /* some number->text resolving which is time consuming and kind of insane */ if (flags & PROC_FILLUSR){ memcpy(p->euser, user_from_uid(p->euid), sizeof p->euser); if(flags & PROC_FILLSTATUS) { memcpy(p->ruser, user_from_uid(p->ruid), sizeof p->ruser); memcpy(p->suser, user_from_uid(p->suid), sizeof p->suser); memcpy(p->fuser, user_from_uid(p->fuid), sizeof p->fuser); } } /* some number->text resolving which is time consuming and kind of insane */ if (flags & PROC_FILLGRP){ memcpy(p->egroup, group_from_gid(p->egid), sizeof p->egroup); if(flags & PROC_FILLSTATUS) { memcpy(p->rgroup, group_from_gid(p->rgid), sizeof p->rgroup); memcpy(p->sgroup, group_from_gid(p->sgid), sizeof p->sgroup); memcpy(p->fgroup, group_from_gid(p->fgid), sizeof p->fgroup); } } if ((flags & PROC_FILLCOM) || (flags & PROC_FILLARG)) /* read+parse /proc/#/cmdline */ p->cmdline = file2strvec(path, "cmdline"); else p->cmdline = NULL; if (unlikely(flags & PROC_FILLENV)) /* read+parse /proc/#/environ */ p->environ = file2strvec(path, "environ"); else p->environ = NULL; return p;next_proc: return NULL;}//////////////////////////////////////////////////////////////////////////////////// This reads /proc/*/task/* data, for one task.// p is the POSIX process (task group summary) (not needed by THIS implementation)// t is the POSIX thread (task group member, generally not the leader)// path is a path to the task, with some room to spare.static proc_t* simple_readtask(PROCTAB *restrict const PT, const proc_t *restrict const p, proc_t *restrict const t, char *restrict const path) { static struct stat sb; // stat() buffer static char sbuf[1024]; // buffer for stat,statm unsigned flags = PT->flags;//printf("hhh\n"); if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */ goto next_task;// if ((flags & PROC_UID) && !XinLN(uid_t, sb.st_uid, PT->uids, PT->nuid))// goto next_task; /* not one of the requested uids */ t->euid = sb.st_uid; /* need a way to get real uid */ t->egid = sb.st_gid; /* need a way to get real gid *///printf("iii\n"); if (flags & PROC_FILLSTAT) { /* read, parse /proc/#/stat */ if (unlikely( file2str(path, "stat", sbuf, sizeof sbuf) == -1 )) goto next_task; /* error reading /proc/#/stat */ stat2proc(sbuf, t); /* parse /proc/#/stat */ } if (unlikely(flags & PROC_FILLMEM)) { /* read, parse /proc/#/statm */#if 0 if (likely( file2str(path, "statm", sbuf, sizeof sbuf) != -1 )) statm2proc(sbuf, t); /* ignore statm errors here */#else t->size = p->size; t->resident = p->resident; t->share = p->share; t->trs = p->trs; t->lrs = p->lrs; t->drs = p->drs; t->dt = p->dt;#endif } /* statm fields just zero */ if (flags & PROC_FILLSTATUS) { /* read, parse /proc/#/status */ if (likely( file2str(path, "status", sbuf, sizeof sbuf) != -1 )){ status2proc(sbuf, t, 0); } } /* some number->text resolving which is time consuming */ if (flags & PROC_FILLUSR){ memcpy(t->euser, user_from_uid(t->euid), sizeof t->euser); if(flags & PROC_FILLSTATUS) { memcpy(t->ruser, user_from_uid(t->ruid), sizeof t->ruser); memcpy(t->suser, user_from_uid(t->suid), sizeof t->suser); memcpy(t->fuser, user_from_uid(t->fuid), sizeof t->fuser); } } /* some number->text resolving which is time consuming */ if (flags & PROC_FILLGRP){ memcpy(t->egroup, group_from_gid(t->egid), sizeof t->egroup); if(flags & PROC_FILLSTATUS) { memcpy(t->rgroup, group_from_gid(t->rgid), sizeof t->rgroup); memcpy(t->sgroup, group_from_gid(t->sgid), sizeof t->sgroup); memcpy(t->fgroup, group_from_gid(t->fgid), sizeof t->fgroup); } }#if 0 if ((flags & PROC_FILLCOM) || (flags & PROC_FILLARG)) /* read+parse /proc/#/cmdline */ t->cmdline = file2strvec(path, "cmdline"); else t->cmdline = NULL; if (unlikely(flags & PROC_FILLENV)) /* read+parse /proc/#/environ */ t->environ = file2strvec(path, "environ"); else t->environ = NULL;#else t->cmdline = p->cmdline; // better not free these until done with all threads! t->environ = p->environ;#endif t->ppid = p->ppid; // ought to put the per-task ppid somewhere return t;next_task: return NULL;}//////////////////////////////////////////////////////////////////////////////////// This finds processes in /proc in the traditional way.// Return non-zero on success.static int simple_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p) { static struct direct *ent; /* dirent handle */ char *restrict const path = PT->path; for (;;) { ent = readdir(PT->procfs);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -