?? readproc.c
字號:
/* * New Interface to Process Table -- PROCTAB Stream (a la Directory streams) * Copyright (C) 1996 Charles L. Blake. * Copyright (C) 1998 Michael K. Johnson * Copyright 1998-2003 Albert Cahalan * May be distributed under the conditions of the * GNU Library General Public License; a copy is in COPYING */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "version.h"#include "readproc.h"#include "alloc.h"#include "pwcache.h"#include "devname.h"#include "procps.h"#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <stdarg.h>#include <string.h>#include <unistd.h>#include <signal.h>#include <fcntl.h>#include <sys/dir.h>#include <sys/types.h>#include <sys/stat.h>// sometimes it's easier to do this manually, w/o gcc helping#ifdef PROFextern void __cyg_profile_func_enter(void*,void*);#define ENTER(x) __cyg_profile_func_enter((void*)x,(void*)x)#define LEAVE(x) __cyg_profile_func_exit((void*)x,(void*)x)#else#define ENTER(x)#define LEAVE(x)#endif// convert hex string to unsigned long longstatic unsigned long long unhex(const char *restrict cp){ unsigned long long ull = 0; for(;;){ char c = *cp++; if(unlikely(c<0x30)) break; ull = (ull<<4) | (c - (c>0x57) ? 0x57 : 0x30) ; } return ull;}static int task_dir_missing;///////////////////////////////////////////////////////////////////////////typedef struct status_table_struct { unsigned char name[7]; // /proc/*/status field name unsigned char len; // name length#ifdef LABEL_OFFSET long offset; // jump address offset#else void *addr;#endif} status_table_struct;#ifdef LABEL_OFFSET#define F(x) {#x, sizeof(#x)-1, (long)(&&case_##x-&&base)},#else#define F(x) {#x, sizeof(#x)-1, &&case_##x},#endif#define NUL {"", 0, 0},// Derived from:// gperf -7 --language=ANSI-C --key-positions=1,3,4 -C -n -c sml.gperf//// Suggested method:// Grep this file for "case_", then strip those down to the name.// (leave the colon and newline) So "Pid:\n" and "Threads:\n"// would be lines in the file. (no quote, no escape, etc.)//// Watch out for name size in the status_table_struct (grrr, expanding)// and the number of entries (we mask with 63 for now). The table// must be padded out to 64 entries, maybe 128 in the future.static void status2proc(char *S, proc_t *restrict P, int is_proc){ long Threads = 0; long Tgid = 0; long Pid = 0; static const unsigned char asso[] = { 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 15, 61, 61, 61, 61, 61, 61, 61, 30, 3, 5, 5, 61, 5, 61, 8, 61, 61, 3, 61, 10, 61, 6, 61, 13, 0, 30, 25, 0, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 3, 61, 13, 0, 0, 61, 30, 61, 25, 61, 61, 61, 0, 61, 61, 61, 61, 5, 61, 0, 61, 61, 61, 0, 61, 61, 61, 61, 61, 61, 61 }; static const status_table_struct table[] = { F(VmStk) NUL NUL F(State) NUL F(VmExe) F(ShdPnd) NUL F(VmData) NUL F(Name) NUL NUL F(VmRSS) NUL NUL F(VmLck) NUL NUL NUL F(Gid) F(Pid) NUL NUL NUL F(VmSize) NUL NUL F(VmLib) NUL NUL F(PPid) NUL F(SigCgt) NUL F(Threads) F(SigPnd) NUL F(SigIgn) NUL F(Uid) NUL NUL NUL NUL NUL NUL NUL NUL NUL NUL NUL NUL NUL NUL F(Tgid) NUL NUL NUL NUL F(SigBlk) NUL NUL NUL };#undef F#undef NULENTER(0x220); P->vm_size = 0; P->vm_lock = 0; P->vm_rss = 0; P->vm_data = 0; P->vm_stack= 0; P->vm_exe = 0; P->vm_lib = 0; P->nlwp = 0; P->signal[0] = '\0'; // so we can detect it as missing for very old kernels goto base; for(;;){ char *colon; status_table_struct entry; // advance to next line S = strchr(S, '\n'); if(unlikely(!S)) break; // if no newline S++; // examine a field name (hash and compare) base: if(unlikely(!*S)) break; entry = table[63 & (asso[S[3]] + asso[S[2]] + asso[S[0]])]; colon = strchr(S, ':'); if(unlikely(!colon)) break; if(unlikely(colon[1]!='\t')) break; if(unlikely(colon-S != entry.len)) continue; if(unlikely(memcmp(entry.name,S,colon-S))) continue; S = colon+2; // past the '\t'#ifdef LABEL_OFFSET goto *(&&base + entry.offset);#else goto *entry.addr;#endif case_Name:{ unsigned u = 0; while(u < sizeof P->cmd - 1u){ int c = *S++; if(unlikely(c=='\n')) break; if(unlikely(c=='\0')) break; // should never happen if(unlikely(c=='\\')){ c = *S++; if(c=='\n') break; // should never happen if(!c) break; // should never happen if(c=='n') c='\n'; // else we assume it is '\\' } P->cmd[u++] = c; } P->cmd[u] = '\0'; S--; // put back the '\n' or '\0' continue; }#ifdef SIGNAL_STRING case_ShdPnd: memcpy(P->signal, S, 16); P->signal[16] = '\0'; continue; case_SigBlk: memcpy(P->blocked, S, 16); P->blocked[16] = '\0'; continue; case_SigCgt: memcpy(P->sigcatch, S, 16); P->sigcatch[16] = '\0'; continue; case_SigIgn: memcpy(P->sigignore, S, 16); P->sigignore[16] = '\0'; continue; case_SigPnd: memcpy(P->_sigpnd, S, 16); P->_sigpnd[16] = '\0'; continue;#else case_ShdPnd: P->signal = unhex(S); continue; case_SigBlk: P->blocked = unhex(S); continue; case_SigCgt: P->sigcatch = unhex(S); continue; case_SigIgn: P->sigignore = unhex(S); continue; case_SigPnd: P->_sigpnd = unhex(S); continue;#endif case_State: P->state = *S; continue; case_Tgid: Tgid = strtol(S,&S,10); continue; case_Pid: Pid = strtol(S,&S,10); continue; case_PPid: P->ppid = strtol(S,&S,10); continue; case_Threads: Threads = strtol(S,&S,10); continue; case_Uid: P->ruid = strtol(S,&S,10); P->euid = strtol(S,&S,10); P->suid = strtol(S,&S,10); P->fuid = strtol(S,&S,10); continue; case_Gid: P->rgid = strtol(S,&S,10); P->egid = strtol(S,&S,10); P->sgid = strtol(S,&S,10); P->fgid = strtol(S,&S,10); continue; case_VmData: P->vm_data = strtol(S,&S,10); continue; case_VmExe: P->vm_exe = strtol(S,&S,10); continue; case_VmLck: P->vm_lock = strtol(S,&S,10); continue; case_VmLib: P->vm_lib = strtol(S,&S,10); continue; case_VmRSS: P->vm_rss = strtol(S,&S,10); continue; case_VmSize: P->vm_size = strtol(S,&S,10); continue; case_VmStk: P->vm_stack = strtol(S,&S,10); continue; }#if 0 // recent kernels supply per-tgid pending signals if(is_proc && *ShdPnd){ memcpy(P->signal, ShdPnd, 16); P->signal[16] = '\0'; }#endif // recent kernels supply per-tgid pending signals#ifdef SIGNAL_STRING if(!is_proc || !P->signal[0]){ memcpy(P->signal, P->_sigpnd, 16); P->signal[16] = '\0'; }#else if(!is_proc || !have_process_pending){ P->signal = P->_sigpnd; }#endif // Linux 2.4.13-pre1 to max 2.4.xx have a useless "Tgid" // that is not initialized for built-in kernel tasks. // Only 2.6.0 and above have "Threads" (nlwp) info. if(Threads){ P->nlwp = Threads; P->tgid = Tgid; // the POSIX PID value P->tid = Pid; // the thread ID }else{ P->nlwp = 1; P->tgid = Pid; P->tid = Pid; }LEAVE(0x220);}///////////////////////////////////////////////////////////////////////// Reads /proc/*/stat files, being careful not to trip over processes with// names like ":-) 1 2 3 4 5 6".static void stat2proc(const char* S, proc_t *restrict P) { unsigned num; char* tmp;ENTER(0x160); /* fill in default values for older kernels */ P->processor = 0; P->rtprio = -1; P->sched = -1; P->nlwp = 0; S = strchr(S, '(') + 1; tmp = strrchr(S, ')'); num = tmp - S;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -