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

📄 top.c

📁 手机嵌入式Linux下可用的busybox源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * A tiny 'top' utility. * * This is written specifically for the linux /proc/<PID>/stat(m) * files format. * This reads the PIDs of all processes and their status and shows * the status of processes (first ones that fit to screen) at given * intervals. *  * NOTES: * - At startup this changes to /proc, all the reads are then *   relative to that. *  * (C) Eero Tamminen <oak at welho dot com> * * Rewroted by Vladimir Oleynik (C) 2002 <dzo@simtreas.ru> *//* Original code Copyrights *//* * Copyright (c) 1992 Branko Lankester * Copyright (c) 1992 Roger Binns * Copyright (C) 1994-1996 Charles L. Blake. * Copyright (C) 1992-1998 Michael K. Johnson * May be distributed under the conditions of the * GNU Library General Public License */#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <dirent.h>#include <string.h>#include <sys/ioctl.h>#include <sys/stat.h>/* get page info */#include <asm/page.h>#include "busybox.h"#define FEATURE_CPU_USAGE_PERCENTAGE  /* + 2k */#ifdef FEATURE_CPU_USAGE_PERCENTAGE#include <time.h>#include <sys/time.h>#include <fcntl.h>#include <netinet/in.h>  /* htons */#endiftypedef struct {	int pid;	char user[9];	char state[4];	unsigned long rss;	int ppid;#ifdef FEATURE_CPU_USAGE_PERCENTAGE	unsigned pcpu;	unsigned long stime, utime;#endif	char *cmd;	/* basename of executable file in call to exec(2),		size from kernel headers */	char short_cmd[16];} status_t;typedef int (*cmp_t)(status_t *P, status_t *Q);static status_t *top;   /* Hehe */static int ntop;static int pid_sort (status_t *P, status_t *Q){    int p = P->pid;    int q = Q->pid;    if( p < q ) return -1;    if( p > q ) return  1;    return 0;}static int mem_sort (status_t *P, status_t *Q){    long p = P->rss;    long q = Q->rss;    if( p > q ) return -1;    if( p < q ) return  1;    return 0;}#ifdef FEATURE_CPU_USAGE_PERCENTAGE#define sort_depth 3static cmp_t sort_function[sort_depth];static int pcpu_sort (status_t *P, status_t *Q){    int p = P->pcpu;    int q = Q->pcpu;    if( p > q ) return -1;    if( p < q ) return  1;    return 0;}static int time_sort (status_t *P, status_t *Q){    long p = P->stime;    long q = Q->stime;    p += P->utime;    q += Q->utime;    if( p > q ) return -1;    if( p < q ) return  1;    return 0;}int mult_lvl_cmp(void* a, void* b) {    int i, cmp_val;    for(i = 0; i < sort_depth; i++) {	cmp_val = (*sort_function[i])(a, b);	if (cmp_val != 0)	    return cmp_val;    }    return 0;}/* This structure stores some critical information from one frame to   the next. mostly used for sorting. Added cumulative and resident fields. */struct save_hist {    int ticks;    int pid;    int utime;    int stime;};/* * Calculates percent cpu usage for each task. */static struct save_hist *save_history;static unsigned long Hertz;/*********************************************************************** * Some values in /proc are expressed in units of 1/HZ seconds, where HZ * is the kernel clock tick rate. One of these units is called a jiffy. * The HZ value used in the kernel may vary according to hacker desire. * According to Linus Torvalds, this is not true. He considers the values * in /proc as being in architecture-dependant units that have no relation * to the kernel clock tick rate. Examination of the kernel source code * reveals that opinion as wishful thinking. * * In any case, we need the HZ constant as used in /proc. (the real HZ value * may differ, but we don't care) There are several ways we could get HZ: * * 1. Include the kernel header file. If it changes, recompile this library. * 2. Use the sysconf() function. When HZ changes, recompile the C library! * 3. Ask the kernel. This is obviously correct... * * Linus Torvalds won't let us ask the kernel, because he thinks we should * not know the HZ value. Oh well, we don't have to listen to him. * Someone smuggled out the HZ value. :-) * * This code should work fine, even if Linus fixes the kernel to match his * stated behavior. The code only fails in case of a partial conversion. * */#define FILE_TO_BUF(filename, fd) do{                           \    if (fd == -1 && (fd = open(filename, O_RDONLY)) == -1) {    \	perror_msg_and_die("/proc not be mounted?");            \    }                                                           \    lseek(fd, 0L, SEEK_SET);                                    \    if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) {        \	perror_msg_and_die("%s", filename);                     \    }                                                           \    buf[local_n] = '\0';                                        \}while(0)#define FILE_TO_BUF2(filename, fd) do{                          \    lseek(fd, 0L, SEEK_SET);                                    \    if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) {        \	perror_msg_and_die("%s", filename);                     \    }                                                           \    buf[local_n] = '\0';                                        \}while(0)static void init_Hertz_value(void) {  unsigned long user_j, nice_j, sys_j, other_j;  /* jiffies (clock ticks) */  double up_1, up_2, seconds;  unsigned long jiffies, h;  char buf[80];  int uptime_fd = -1;  int stat_fd = -1;  long smp_num_cpus = sysconf(_SC_NPROCESSORS_CONF);  if(smp_num_cpus<1) smp_num_cpus=1;  do {    int local_n;    FILE_TO_BUF("uptime", uptime_fd);    up_1 = strtod(buf, 0);    FILE_TO_BUF("stat", stat_fd);    sscanf(buf, "cpu %lu %lu %lu %lu", &user_j, &nice_j, &sys_j, &other_j);    FILE_TO_BUF2("uptime", uptime_fd);    up_2 = strtod(buf, 0);  } while((long)( (up_2-up_1)*1000.0/up_1 )); /* want under 0.1% error */  close(uptime_fd);  close(stat_fd);  jiffies = user_j + nice_j + sys_j + other_j;  seconds = (up_1 + up_2) / 2;  h = (unsigned long)( (double)jiffies/seconds/smp_num_cpus );  /* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */  switch(h){  case   30 ...   34 :  Hertz =   32; break; /* ia64 emulator */  case   48 ...   52 :  Hertz =   50; break;  case   58 ...   62 :  Hertz =   60; break;  case   63 ...   65 :  Hertz =   64; break; /* StrongARM /Shark */  case   95 ...  105 :  Hertz =  100; break; /* normal Linux */  case  124 ...  132 :  Hertz =  128; break; /* MIPS, ARM */  case  195 ...  204 :  Hertz =  200; break; /* normal << 1 */  case  253 ...  260 :  Hertz =  256; break;  case  295 ...  304 :  Hertz =  300; break; /* 3 cpus */  case  393 ...  408 :  Hertz =  400; break; /* normal << 2 */  case  495 ...  504 :  Hertz =  500; break; /* 5 cpus */  case  595 ...  604 :  Hertz =  600; break; /* 6 cpus */  case  695 ...  704 :  Hertz =  700; break; /* 7 cpus */  case  790 ...  808 :  Hertz =  800; break; /* normal << 3 */  case  895 ...  904 :  Hertz =  900; break; /* 9 cpus */  case  990 ... 1010 :  Hertz = 1000; break; /* ARM */  case 1015 ... 1035 :  Hertz = 1024; break; /* Alpha, ia64 */  case 1095 ... 1104 :  Hertz = 1100; break; /* 11 cpus */  case 1180 ... 1220 :  Hertz = 1200; break; /* Alpha */  default:    /* If 32-bit or big-endian (not Alpha or ia64), assume HZ is 100. */    Hertz = (sizeof(long)==sizeof(int) || htons(999)==999) ? 100UL : 1024UL;  }}static void do_stats(void){    struct timeval t;    static struct timeval oldtime;    struct timezone timez;    float elapsed_time;    status_t *cur;    int total_time, i, n;    static int prev_count;    int systime, usrtime, pid;    struct save_hist *New_save_hist;    /*     * Finds the current time (in microseconds) and calculates the time     * elapsed since the last update.     */    gettimeofday(&t, &timez);    elapsed_time = (t.tv_sec - oldtime.tv_sec)	+ (float) (t.tv_usec - oldtime.tv_usec) / 1000000.0;    oldtime.tv_sec  = t.tv_sec;    oldtime.tv_usec = t.tv_usec;    New_save_hist  = alloca(sizeof(struct save_hist)*ntop);    /*     * Make a pass through the data to get stats.     */    for(n = 0; n < ntop; n++) {	cur = top + n;	/*	 * Calculate time in cur process.  Time is sum of user time	 * (usrtime) plus system time (systime).	 */	systime = cur->stime;	usrtime = cur->utime;	pid = cur->pid;	total_time = systime + usrtime;	New_save_hist[n].ticks = total_time;	New_save_hist[n].pid = pid;	New_save_hist[n].stime = systime;	New_save_hist[n].utime = usrtime;	/* find matching entry from previous pass */	for (i = 0; i < prev_count; i++) {	    if (save_history[i].pid == pid) {		total_time -= save_history[i].ticks;		systime -= save_history[i].stime;		usrtime -= save_history[i].utime;		break;	    }	}	/*	 * Calculate percent cpu time for cur task.	 */	i = (total_time * 10 * 100/Hertz) / elapsed_time;	if (i > 999)	    i = 999;	cur->pcpu = i;    }    /*     * Save cur frame's information.     */    free(save_history);    save_history = memcpy(xmalloc(sizeof(struct save_hist)*n), New_save_hist,						sizeof(struct save_hist)*n);    prev_count = n;    qsort(top, n, sizeof(status_t), (void*)mult_lvl_cmp);}#elsestatic cmp_t sort_function;#endif /* FEATURE_CPU_USAGE_PERCENTAGE *//* display generic info (meminfo / loadavg) */static unsigned long display_generic(void){	FILE *fp;	char buf[80];	float avg1, avg2, avg3;	unsigned long total, used, mfree, shared, buffers, cached;	/* read memory info */	fp = xfopen("meminfo", "r");	fgets(buf, sizeof(buf), fp);	/* skip first line */	if (fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu",		   &total, &used, &mfree, &shared, &buffers, &cached) != 6) {		error_msg_and_die("failed to read '%s'", "meminfo");	}	fclose(fp);		/* read load average */	fp = xfopen("loadavg", "r");	if (fscanf(fp, "%f %f %f", &avg1, &avg2, &avg3) != 3) {		error_msg_and_die("failed to read '%s'", "loadavg");	}	fclose(fp);	/* convert to kilobytes */	used /= 1024;

⌨️ 快捷键说明

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