📄 m_linuxthr.c
字号:
/* * top - a top users display for Unix * * SYNOPSIS: 2.x with thread eliding * * DESCRIPTION: * This is the machine-dependent module for Linux 2.x that elides threads * from the output. * * CFLAGS: -DHAVE_GETOPT -DHAVE_STRERROR -DORDER * * TERMCAP: -lcurses * * AUTHOR: Richard Henderson <rth@tamu.edu> * Order support added by Alexey Klimkin <kad@klon.tme.mcst.ru> * Ported to 2.4 by William LeFebvre * Thread eliding by William LeFebvre */#include "top.h"#include "machine.h"#include "utils.h"#include <sys/types.h>#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <errno.h>#include <dirent.h>#include <string.h>#include <math.h>#include <ctype.h>#include <sys/time.h>#include <sys/stat.h>#include <sys/vfs.h>#include <sys/param.h> /* for HZ */#include <asm/page.h> /* for PAGE_SHIFT */#if 0#include <linux/proc_fs.h> /* for PROC_SUPER_MAGIC */#else#define PROC_SUPER_MAGIC 0x9fa0#endif#define PROCFS "/proc"extern char *myname;extern uid_t proc_owner(pid_t pid);/*=PROCESS INFORMATION==================================================*/struct top_proc{ pid_t pid; pid_t ppid; uid_t uid; char name[64]; int pri, nice; unsigned long size, rss; /* in k */ int state; unsigned long time; unsigned long otime; unsigned long start_code; unsigned long end_code; unsigned long start_stack; unsigned int threads; double pcpu, wcpu; struct top_proc *next;}; /*=STATE IDENT STRINGS==================================================*/#define NPROCSTATES 7static char *state_abbrev[NPROCSTATES+1] ={ "", "run", "sleep", "disk", "zomb", "stop", "swap", NULL};static char *procstatenames[NPROCSTATES+1] ={ "", " running, ", " sleeping, ", " uninterruptable, ", " zombie, ", " stopped, ", " swapping, ", NULL};#define NCPUSTATES 4static char *cpustatenames[NCPUSTATES+1] ={ "user", "nice", "system", "idle", NULL};#define NMEMSTATS 6static char *memorynames[NMEMSTATS+1] ={ "K used, ", "K free, ", "K shd, ", "K buf Swap: ", "K used, ", "K free", NULL};static char fmt_header[] =" PID X THR PRI NICE SIZE RES STATE TIME CPU COMMAND";#ifdef ORDER/* these are names given to allowed sorting orders -- first is default */char *ordernames[] = {"cpu", "size", "res", "time", NULL};/* forward definitions for comparison functions */int compare_cpu();int compare_size();int compare_res();int compare_time();int (*proc_compares[])() = { compare_cpu, compare_size, compare_res, compare_time, NULL };#endif /*=SYSTEM STATE INFO====================================================*//* these are for calculating cpu state percentages */static long cp_time[NCPUSTATES];static long cp_old[NCPUSTATES];static long cp_diff[NCPUSTATES];/* for calculating the exponential average */static struct timeval lasttime;/* these are for keeping track of processes */#define HASH_SIZE (1003)#define INITIAL_ACTIVE_SIZE (256)#define PROCBLOCK_SIZE (32)static struct top_proc *ptable[HASH_SIZE];static struct top_proc **pactive;static struct top_proc **nextactive;unsigned int activesize = 0;/* these are for passing data back to the machine independant portion */static int cpu_states[NCPUSTATES];static int process_states[NPROCSTATES];static int memory_stats[NMEMSTATS];/* usefull macros */#define bytetok(x) (((x) + 512) >> 10)#define pagetok(x) ((x) << (PAGE_SHIFT - 10))#define HASH(x) (((x) * 1686629713U) % HASH_SIZE)/*======================================================================*/static inline char *skip_ws(const char *p){ while (isspace(*p)) p++; return (char *)p;} static inline char *skip_token(const char *p){ while (isspace(*p)) p++; while (*p && !isspace(*p)) p++; return (char *)p;}/* * Process structures are allocated and freed as needed. Here we * keep big pools of them, adding more pool as needed. When a * top_proc structure is freed, it is added to a freelist and reused. */static struct top_proc *freelist = NULL;static struct top_proc *procblock = NULL;static struct top_proc *procmax = NULL;static struct top_proc*new_proc(){ struct top_proc *p; if (freelist) { p = freelist; freelist = freelist->next; } else if (procblock) { p = procblock; if (++procblock >= procmax) { procblock = NULL; } } else { p = procblock = (struct top_proc *)malloc(sizeof(struct top_proc) * PROCBLOCK_SIZE); procmax = procblock++ + PROCBLOCK_SIZE; } return p;}static voidfree_proc(struct top_proc *proc){ proc->next = freelist; freelist = proc;} intmachine_init(statics) struct statics *statics;{ /* make sure the proc filesystem is mounted */ { struct statfs sb; if (statfs(PROCFS, &sb) < 0 || sb.f_type != PROC_SUPER_MAGIC) { fprintf(stderr, "%s: proc filesystem not mounted on " PROCFS "\n", myname); return -1; } } /* chdir to the proc filesystem to make things easier */ chdir(PROCFS); /* initialize the process hash table */ { int i; for (i = 0; i < HASH_SIZE; ++i) ptable[i] = NULL; } /* fill in the statics information */ statics->procstate_names = procstatenames; statics->cpustate_names = cpustatenames; statics->memory_names = memorynames;#ifdef ORDER statics->order_names = ordernames;#endif /* allocate needed space */ pactive = (struct top_proc **)malloc(sizeof(struct top_proc *) * INITIAL_ACTIVE_SIZE); activesize = INITIAL_ACTIVE_SIZE; /* make sure the hash table is empty */ memset(ptable, 0, HASH_SIZE * sizeof(struct top_proc *)); /* all done! */ return 0;}voidget_system_info(info) struct system_info *info;{ char buffer[4096+1]; int fd, len; char *p; /* get load averages */ { fd = open("loadavg", O_RDONLY); len = read(fd, buffer, sizeof(buffer)-1); close(fd); buffer[len] = '\0'; info->load_avg[0] = strtod(buffer, &p); info->load_avg[1] = strtod(p, &p); info->load_avg[2] = strtod(p, &p); p = skip_token(p); /* skip running/tasks */ p = skip_ws(p); if (*p) info->last_pid = atoi(p); else info->last_pid = -1; } /* get the cpu time info */ { fd = open("stat", O_RDONLY); len = read(fd, buffer, sizeof(buffer)-1); close(fd); buffer[len] = '\0'; p = skip_token(buffer); /* "cpu" */ cp_time[0] = strtoul(p, &p, 0); cp_time[1] = strtoul(p, &p, 0); cp_time[2] = strtoul(p, &p, 0); cp_time[3] = strtoul(p, &p, 0); /* convert cp_time counts to percentages */ percentages(4, cpu_states, cp_time, cp_old, cp_diff); } /* get system wide memory usage */ { char *p; fd = open("meminfo", O_RDONLY); len = read(fd, buffer, sizeof(buffer)-1); close(fd); buffer[len] = '\0'; /* be prepared for extra columns to appear be seeking to ends of lines */ p = strchr(buffer, '\n'); p = skip_token(p); /* "Mem:" */ p = skip_token(p); /* total memory */ memory_stats[0] = strtoul(p, &p, 10); memory_stats[1] = strtoul(p, &p, 10); memory_stats[2] = strtoul(p, &p, 10); memory_stats[3] = strtoul(p, &p, 10); p = strchr(p, '\n'); p = skip_token(p); /* "Swap:" */ p = skip_token(p); /* total swap */ memory_stats[4] = strtoul(p, &p, 10); memory_stats[5] = strtoul(p, &p, 10); memory_stats[0] = bytetok(memory_stats[0]); memory_stats[1] = bytetok(memory_stats[1]); memory_stats[2] = bytetok(memory_stats[2]); memory_stats[3] = bytetok(memory_stats[3]); memory_stats[4] = bytetok(memory_stats[4]); memory_stats[5] = bytetok(memory_stats[5]); } /* set arrays and strings */ info->cpustates = cpu_states; info->memory = memory_stats;}static voidread_one_proc_stat(pid_t pid, struct top_proc *proc){ char buffer[4096], *p; /* grab the proc stat info in one go */ { int fd, len; sprintf(buffer, "%d/stat", pid); fd = open(buffer, O_RDONLY); len = read(fd, buffer, sizeof(buffer)-1); close(fd); buffer[len] = '\0'; } proc->uid = proc_owner(pid); /* parse out the status */ p = buffer; p = strchr(p, '(')+1; /* skip pid */ { char *q = strrchr(p, ')'); int len = q-p; if (len >= sizeof(proc->name)) len = sizeof(proc->name)-1; memcpy(proc->name, p, len); proc->name[len] = 0; p = q+1; } p = skip_ws(p); switch (*p++) { case 'R': proc->state = 1; break; case 'S': proc->state = 2; break; case 'D': proc->state = 3; break; case 'Z': proc->state = 4; break; case 'T': proc->state = 5; break; case 'W': proc->state = 6; break; } proc->ppid = strtoul(p, &p, 10); /* skip ppid */ p = skip_token(p); /* skip pgrp */ p = skip_token(p); /* skip session */ p = skip_token(p); /* skip tty */ p = skip_token(p); /* skip tty pgrp */ p = skip_token(p); /* skip flags */ p = skip_token(p); /* skip min flt */ p = skip_token(p); /* skip cmin flt */ p = skip_token(p); /* skip maj flt */ p = skip_token(p); /* skip cmaj flt */ proc->time = strtoul(p, &p, 10); /* utime */ proc->time += strtoul(p, &p, 10); /* stime */ p = skip_token(p); /* skip cutime */ p = skip_token(p); /* skip cstime */ proc->pri = strtol(p, &p, 10); /* priority */ proc->nice = strtol(p, &p, 10); /* nice */ p = skip_token(p); /* skip timeout */ p = skip_token(p); /* skip it_real_val */ p = skip_token(p); /* skip start_time */ proc->size = bytetok(strtoul(p, &p, 10)); /* vsize */ proc->rss = pagetok(strtoul(p, &p, 10)); /* rss */ p = skip_token(p); /* skip rlim */ proc->start_code = strtoul(p, &p, 10); /* skip start_code */ proc->end_code = strtoul(p, &p, 10); /* skip end_code */ proc->start_stack = strtoul(p, &p, 10); /* skip start_stack */ /* for the record, here are the rest of the fields */#if 0 p = skip_token(p); /* skip sp */ p = skip_token(p); /* skip pc */ p = skip_token(p); /* skip signal */ p = skip_token(p); /* skip sigblocked */ p = skip_token(p); /* skip sigignore */ p = skip_token(p); /* skip sigcatch */ p = skip_token(p); /* skip wchan */#endif}caddr_tget_process_info(struct system_info *si, struct process_select *sel, int (*compare)()){ struct timeval thistime; double timediff, alpha, beta; struct top_proc *proc; pid_t pid; int i; /* calculate the time difference since our last check */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -