⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readproc.c

📁 Linux下进程监控相关源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * New Interface to Process Table -- PROCTAB Stream (a la Directory streams) * Copyright (C) 1996 Charles L. Blake. * Copyright (C) 1998 Michael K. Johnson * May be distributed under the conditions of the * GNU Library General Public License; a copy is in COPYING */#include "proc/version.h"#include "proc/readproc.h"#include "proc/devname.h"#include "proc/procps.h"#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <sys/dir.h>#include <sys/types.h>#include <sys/stat.h>#define Do(x) (flags & PROC_ ## x)	/* convenient shorthand *//* initiate a process table scan */PROCTAB* openproc(int flags, ...) {    va_list ap;    PROCTAB* PT = xmalloc(sizeof(PROCTAB));        if (Do(PID))      PT->procfs = NULL;    else if (!(PT->procfs = opendir("/proc")))      return NULL;    PT->flags = flags;    va_start(ap, flags);		/*  Init args list */    if (Do(PID))    	PT->pids = va_arg(ap, pid_t*);    else if (Do(TTY))    	PT->ttys = va_arg(ap, dev_t*);    else if (Do(UID)) {    	PT->uids = va_arg(ap, uid_t*);	PT->nuid = va_arg(ap, int);    } else if (Do(STAT))    	PT->stats = va_arg(ap, char*);    va_end(ap);				/*  Clean up args list */    if (Do(ANYTTY) && Do(TTY))	PT->flags = PT->flags & ~PROC_TTY; /* turn off TTY flag */    return PT;}/* terminate a process table scan */void closeproc(PROCTAB* PT) {    if (PT->procfs) closedir(PT->procfs);    if (PT)         free(PT);}/* deallocate the space allocated by readproc if the passed rbuf was NULL */void freeproc(proc_t* p) {    if (!p)	/* in case p is NULL */	return;    /* ptrs are after strings to avoid copying memory when building them. */    /* so free is called on the address of the address of strvec[0]. */    if (p->cmdline)	free((void*)*p->cmdline);    if (p->environ)	free((void*)*p->environ);    free(p);}void status2proc (char* S, proc_t* P, int fill) {    char* tmp;    if (fill == 1) {        memset(P->cmd, 0, sizeof P->cmd);        sscanf (S, "Name:\t%15c", P->cmd);        tmp = strchr(P->cmd,'\n');        *tmp='\0';        tmp = strstr (S,"State");        sscanf (tmp, "State:\t%c", &P->state);    }    tmp = strstr (S,"Pid:");    if(tmp) sscanf (tmp,        "Pid:\t%d\n"        "PPid:\t%d\n",        &P->pid,        &P->ppid    );    else fprintf(stderr, "Internal error!\n");    tmp = strstr (S,"Uid:");    if(tmp) sscanf (tmp,        "Uid:\t%d\t%d\t%d\t%d",        &P->ruid, &P->euid, &P->suid, &P->fuid    );    else fprintf(stderr, "Internal error!\n");    tmp = strstr (S,"Gid:");    if(tmp) sscanf (tmp,        "Gid:\t%d\t%d\t%d\t%d",        &P->rgid, &P->egid, &P->sgid, &P->fgid    );    else fprintf(stderr, "Internal error!\n");    tmp = strstr (S,"VmSize:");    if(tmp) sscanf (tmp,        "VmSize: %lu kB\n"        "VmLck: %lu kB\n"        "VmRSS: %lu kB\n"        "VmData: %lu kB\n"        "VmStk: %lu kB\n"        "VmExe: %lu kB\n"        "VmLib: %lu kB\n",        &P->vm_size, &P->vm_lock, &P->vm_rss, &P->vm_data,        &P->vm_stack, &P->vm_exe, &P->vm_lib    );    else /* looks like an annoying kernel thread */    {        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;    }    tmp = strstr (S,"SigPnd:");    if(tmp) sscanf (tmp,#ifdef SIGNAL_STRING        "SigPnd: %s SigBlk: %s SigIgn: %s %*s %s",        P->signal, P->blocked, P->sigignore, P->sigcatch#else        "SigPnd: %Lx SigBlk: %Lx SigIgn: %Lx %*s %Lx",        &P->signal, &P->blocked, &P->sigignore, &P->sigcatch#endif    );    else fprintf(stderr, "Internal error!\n");}/* stat2proc() makes sure it can handle arbitrary executable file basenames   for `cmd', i.e. those with embedded whitespace or embedded ')'s.  Such names   confuse %s (see scanf(3)), so the string is split and %39c is used instead.   (except for embedded ')' "(%[^)]c)" would work.*/void stat2proc(char* S, proc_t* P) {    int num;    char* tmp = strrchr(S, ')');	/* split into "PID (cmd" and "<rest>" */    *tmp = '\0';			/* replace trailing ')' with NUL */    /* parse these two strings separately, skipping the leading "(". */    memset(P->cmd, 0, sizeof P->cmd);	/* clear even though *P xcalloc'd ?! */    sscanf(S, "%d (%15c", &P->pid, P->cmd);   /* comm[16] in kernel */    num = sscanf(tmp + 2,			/* skip space after ')' too */       "%c "       "%d %d %d %d %d "       "%lu %lu %lu %lu %lu %lu %lu "       "%ld %ld %ld %ld %ld %ld "       "%lu %lu "       "%ld "       "%lu %lu %lu %lu %lu %lu "       "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */       "%lu %lu %lu %*d %d",       &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->timeout, &P->it_real_value,       &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 /* , &P->exit_signal  */, &P->lproc);/* TODO: add &P->exit_signal support here, perhaps to identify Linux threads */    /*    fprintf(stderr, "stat2proc converted %d fields.\n",num); */    if (P->tty == 0)	P->tty = -1;  /* the old notty val, update elsewhere bef. moving to 0 */    if (linux_version_code < LINUX_VERSION(1,3,39)) {	P->priority = 2*15 - P->priority;	/* map old meanings to new */	P->nice = 15 - P->nice;    }    if (linux_version_code < LINUX_VERSION(1,1,30) && P->tty != -1)	P->tty = 4*0x100 + P->tty;		/* when tty wasn't full devno */}void statm2proc(char* s, proc_t* 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); */}void nulls2sep(char* str, int len, char sep) {    int i;    for (i = 0; i < len; i++)    	if (str[i] == 0)    	    str[i] = sep;}int file2str(char *directory, char *what, char *ret, int cap) {    static char filename[80];    int fd, num_read;    sprintf(filename, "%s/%s", directory, what);    if ( (fd       = open(filename, O_RDONLY, 0)) == -1 ) return -1;    if ( (num_read = read(fd, ret, cap - 1))      <= 0 ) num_read = -1;    else ret[num_read] = 0;    close(fd);    return num_read;}char** file2strvec(char* directory, 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);    if ( (fd = open(buf, O_RDONLY, 0) ) == -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 < 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;}/* 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;			\	} )/* readproc: return a pointer to a proc_t filled with requested info about the * next process available matching the restriction set.  If no more such * processes are available, return a null pointer (boolean false).  Use the * passed buffer instead of allocating space if it is non-NULL.  *//* This is optimized so that if a PID list is given, only those files are * searched for in /proc.  If other lists are given in addition to the PID list, * the same logic can follow through as for the no-PID list case.  This is * fairly complex, but it does try to not to do any unnecessary work. * Unfortunately, the reverse filtering option in which any PID *except* the * ones listed is pursued. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -