📄 monitor.c
字号:
/* * Collect system's load information from proc pseudo filesystem. * * Copyright (c) 2004, by: Jian Shen * All rights reserved. Peking University, China * <shenjian@net.pku.edu.cn> * * This file may be used subject to the terms and conditions of the * GNU Library General Public License Version 2, or any later version * at your option, as published by the Free Software Foundation. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * */#include "monitor.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/sysinfo.h>#include <math.h>#include <glob.h>#include <pwd.h>#include <time.h>#include <unistd.h>#include <asm/param.h>#define BUFSIZE 10000#define MAXLENGTH 128/* #ifndef HZ *//* #define HZ (sizeof(long)==sizeof(int)?100:1024) *//* #endif */#ifndef PAGESIZE#define PAGESIZE (sizeof(long)==sizeof(int)?4096:16384)#endif#define TRIMz(x) (x < 0 ? 0 : x)static void cpu_util_init();void monitor_init() { get_cpu_count(); mon_cpu_freq = (double*)malloc(mon_cpu_count*sizeof(double)); mon_cpu_util = (double*)malloc(mon_cpu_count*sizeof(double)); tm_user = (long*)malloc(mon_cpu_count*sizeof(long)); tm_nice = (long*)malloc(mon_cpu_count*sizeof(long)); tm_sys = (long*)malloc(mon_cpu_count*sizeof(long)); tm_idle = (long*)malloc(mon_cpu_count*sizeof(long)); get_total_memory(); get_cpu_clock_speed(); cpu_util_init();}void monitor_cleanup(){ if(mon_cpu_freq != NULL) { free(mon_cpu_freq); mon_cpu_freq = NULL; } if(mon_cpu_util != NULL) { free(mon_cpu_util); mon_cpu_util = NULL; } if(tm_user != NULL) { free(tm_user); tm_user=NULL; } if(tm_nice != NULL) { free(tm_nice); tm_nice=NULL; } if(tm_sys != NULL) { free(tm_sys); tm_sys=NULL; } if(tm_idle != NULL) { free(tm_idle); tm_idle=NULL; }}void get_total_memory(){ struct sysinfo info; sysinfo(&info); mon_total_mem = info.totalram * info.mem_unit / 1024;}void get_free_memory(){ struct sysinfo info; sysinfo(&info); mon_free_mem = info.freeram * info.mem_unit / 1024;}void get_load_average(){ //get load average for last 1,5,15 minutes getloadavg(mon_load_avg, 3);}void get_cpu_count(){ mon_cpu_count = get_nprocs_conf(); if(mon_cpu_count > MAX_CPUS) mon_cpu_count = MAX_CPUS;}void get_cpu_clock_speed(){ FILE* fp; char buffer[BUFSIZE]; size_t bytes_read; char* match; int i; char* begin; float speed; /* Read the entire contents of /proc/cpuinfo into the buffer. */ fp = fopen ("/proc/cpuinfo", "r"); if(fp == NULL) { perror("fopen in get_cpu_clock_speed()"); return; } bytes_read = fread (buffer, 1, sizeof (buffer), fp); fclose (fp); /* Bail if read failed or if buffer isn't big enough. */ if (bytes_read == 0 || bytes_read == sizeof (buffer)) { printf("Reading /proc/cpuinfo failed.\n"); return; } /* NUL-terminate the text. */ buffer[bytes_read] = '\0'; begin = buffer; /* 'begin' points to the begenning of buffer */ for(i=0; i<mon_cpu_count; i++) { /* Locate the line that starts with "cpu MHz". */ match = strstr (begin, "cpu MHz"); if (match == NULL) break; /* Parse the line to extrace the clock speed. */ sscanf (match, "cpu MHz : %f", &speed); mon_cpu_freq[i] = (double)speed; begin += 7; /* skip the last matched "cpu MHZ" */ }}void get_cpu_utilization(){ long *curr_user,*curr_nice,*curr_sys,*curr_idle; FILE* fp; char buffer[BUFSIZE]; size_t bytes_read; char* match; int i; char* begin; char cpuname[10]; int tmp; long total_elapse; curr_user = (long*)malloc(mon_cpu_count*sizeof(long)); curr_nice = (long*)malloc(mon_cpu_count*sizeof(long)); curr_sys = (long*)malloc(mon_cpu_count*sizeof(long)); curr_idle = (long*)malloc(mon_cpu_count*sizeof(long)); /* Read the entire contents of /proc/stat into the buffer. */ fp = fopen ("/proc/stat", "r"); if(fp == NULL) { perror("fopen in get_cpu_utilization()"); goto ret; } bytes_read = fread (buffer, 1, sizeof (buffer), fp); fclose (fp); /* Bail if read failed or if buffer isn't big enough. */ if (bytes_read == 0 || bytes_read == sizeof (buffer)) { printf("Reading /proc/stat failed.\n"); goto ret; } /* NUL-terminate the text. */ buffer[bytes_read] = '\0'; begin = buffer; /* 'begin' points to the begenning of buffer */ for(i=0; i<mon_cpu_count; i++) { bzero(cpuname, 10); sprintf(cpuname, "cpu%d", i); /* Locate the line that starts with cpu name. */ match = strstr (begin, cpuname); if (match == NULL) break; /* Parse the line to extrace the cpu time. */ sscanf (match, "cpu%d %ld %ld %ld %ld", &tmp, &curr_user[i], &curr_nice[i], &curr_sys[i], &curr_idle[i]); begin += 4; /* skip the last matched cpu name */ } /* compute cpu utilization during the last period */ for(i=0; i<mon_cpu_count; i++) { long u_frame = curr_user[i] - tm_user[i]; long s_frame = curr_sys[i] - tm_sys[i]; long n_frame = curr_nice[i] - tm_nice[i]; long i_frame = TRIMz(curr_idle[i] - tm_idle[i]); total_elapse = u_frame + s_frame + n_frame + i_frame; if(total_elapse < 1) total_elapse = 1; mon_cpu_util[i] = 1 - ((double)i_frame / (double)total_elapse); } /* set current cpu time */ for(i=0; i<mon_cpu_count; i++) { tm_user[i] = curr_user[i]; tm_nice[i] = curr_nice[i]; tm_sys[i] = curr_sys[i]; tm_idle[i] = curr_idle[i]; } ret: free(curr_user); free(curr_nice); free(curr_sys); free(curr_idle);}static void cpu_util_init(){ FILE* fp; char buffer[BUFSIZE]; size_t bytes_read; char* match; int i; char* begin; char cpuname[10]; long curr_user, curr_nice, curr_sys, curr_idle; int tmp; /* Read the entire contents of /proc/stat into the buffer. */ fp = fopen ("/proc/stat", "r"); if(fp == NULL) { perror("fopen in cpu_util_init()"); return; } bytes_read = fread (buffer, 1, sizeof (buffer), fp); fclose (fp); /* Bail if read failed or if buffer isn't big enough. */ if (bytes_read == 0 || bytes_read == sizeof (buffer)) { printf("Reading /proc/stat failed.\n"); return; } /* NUL-terminate the text. */ buffer[bytes_read] = '\0'; begin = buffer; /* 'begin' points to the begenning of buffer */ for(i=0; i<mon_cpu_count; i++) { bzero(cpuname, 10); sprintf(cpuname, "cpu%d", i); /* Locate the line that starts with cpu name. */ match = strstr (begin, cpuname); if (match == NULL) break; /* Parse the line to extrace the cpu time. */ sscanf (match, "cpu%d %ld %ld %ld %ld", &tmp, &curr_user, &curr_nice, &curr_sys, &curr_idle); tm_user[i] = curr_user; tm_nice[i] = curr_nice; tm_sys[i] = curr_sys; tm_idle[i] = curr_idle; begin += 4; /* skip the last matched cpu name */ }}/**************************** * Get process list ****************************/struct proc_info { pid_t pid; //1 char comm[MAXLENGTH]; //2 char state; //3 pid_t ppid; //4 pid_t pgrp; //5 int session; //6 int tty_nr; //7 int tpgid; //8 unsigned flags; //9 unsigned minflt; //10 unsigned cminflt; //11 unsigned majflt; //12 unsigned cmajflt; //13 unsigned utime; //14 unsigned stime; //15 int cutime; //16 int cstime; //17 int priority; //18 int nice; //19 int zero; //20 int itrealvalue; //21 unsigned starttime; //22 unsigned vsize; //23 unsigned rss; //24 unsigned rlim; //25 unsigned startcode; //26 unsigned endcode; //27 unsigned startstack; //28 unsigned kstkesp; //29 unsigned kstkeip; //30 unsigned signal; //31 unsigned blocked; //32 unsigned sigignore; //33 unsigned sigcatch; //34 unsigned wchan; //35 unsigned nswap; //36 unsigned cnswap; //37 int exit_signal; //38 int processor; //39};proc_list_t* get_proc_list(){ int i, j, k, uid, size; int totaltime, day, hour, minute, second; double boottime, cpu_percent; char filename[MAXLENGTH]; char cwd[MAXLENGTH], exe[MAXLENGTH]; FILE* f; glob_t globbuf; struct proc_info info; struct passwd pw, *ppw; ppw = &pw; long Hertz = sysconf(_SC_CLK_TCK); if(Hertz < 0) Hertz = HZ; proc_list_t* plist; glob("/proc/[0-9]*", GLOB_NOSORT, NULL, &globbuf); plist = (proc_list_t*)malloc(sizeof(proc_list_t)); if(plist == NULL) return NULL; if(globbuf.gl_pathc > MAX_PROCS) plist->num_of_procs = MAX_PROCS; else plist->num_of_procs = globbuf.gl_pathc; for(k=0; k<plist->num_of_procs; k++) { // i = globbuf.gl_pathc-k-1; i = plist->num_of_procs-k-1; /* read from "stat" */ snprintf(filename, sizeof(filename), "%s%s", globbuf.gl_pathv[i], "/stat"); if((f=fopen(filename, "r"))==NULL) { continue; /* process vanished since glob() */ } fscanf(f, "%d %s %c %d %d %d %d %d %u %u %u %u %u %u %u %d %d %d %d %d %d \ %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %d %d", &info.pid, info.comm, &info.state, &info.ppid, &info.pgrp, &info.session, &info.tty_nr, &info.tpgid, &info.flags, &info.minflt, &info.cminflt, &info.majflt, &info.cmajflt, &info.utime, &info.stime, &info.cutime, &info.cstime, &info.priority, &info.nice, &info.zero, &info.itrealvalue, &info.starttime, &info.vsize, &info.rss, &info.rlim, &info.startcode, &info.endcode, &info.startstack, &info.kstkesp, &info.kstkeip, &info.signal, &info.blocked, &info.sigignore, &info.sigcatch, &info.wchan, &info.nswap, &info.cnswap, &info.exit_signal, &info.processor ); fclose(f); info.comm[0]='['; info.comm[strlen(info.comm)-1]=']'; /* read from "cmdline" */ snprintf(filename, sizeof(filename), "%s%s", globbuf.gl_pathv[i], "/cmdline"); if((f=fopen(filename, "r"))==NULL) { continue; /* process vanished since glob() */ } fgets(info.comm, MAXLENGTH, f); fclose(f); /* read from "status" */ snprintf(filename, sizeof(filename), "%s%s", globbuf.gl_pathv[i], "/status"); if((f=fopen(filename, "r"))==NULL) { continue; // process vanished since glob() } for(j=0; j<30; j++) { fgets(cwd, MAXLENGTH, f); if(strstr(cwd, "Uid")) { sscanf(cwd, "%s\t%d", exe, &uid); exe[0]=0; break; } } fclose(f); /* read from "/proc/uptime" */ snprintf(filename, sizeof(filename), "/proc/uptime"); if((f=fopen(filename, "r"))==NULL) { continue; // process vanished since glob() } fscanf(f, "%lf", &boottime); fclose(f); /* read from "cwd" */ snprintf(filename, sizeof(filename), "%s%s", globbuf.gl_pathv[i], "/cwd"); if((size = readlink(filename, cwd, sizeof(cwd))) < 0) { snprintf(cwd, sizeof(cwd), " "); }else cwd[size] = 0; /* read from "exe" */ snprintf(filename, sizeof(filename), "%s%s", globbuf.gl_pathv[i], "/exe"); if((size = readlink(filename, exe, sizeof(exe))) < 0) { snprintf(exe, sizeof(exe), " "); }else exe[size]=0; /* compute cpu percent */ cpu_percent = (info.utime + info.stime) * 100.0 / (boottime * Hertz - info.starttime); cpu_percent = cpu_percent < 99.9 ? cpu_percent : 99.9; cpu_percent = cpu_percent < 0.001 ? 0 : cpu_percent; /* how long has this proc has been existing */ totaltime = TRIMz((boottime * Hertz - info.starttime)) / Hertz; day = totaltime / (60*60*24); totaltime %= (60*60*24); hour = totaltime / (60*60); totaltime %= (60*60); minute = totaltime / 60; second = totaltime % 60; /* get user information */ ppw = getpwuid(uid); /* USER */ strcpy(plist->procs[k].user, ppw->pw_name); /* PID PPID */ plist->procs[k].pid = info.pid; plist->procs[k].ppid = info.ppid; /* %CPU %MEM */ sprintf(plist->procs[k].cpu_percent, "%.1f", cpu_percent); sprintf(plist->procs[k].mem_percent, "%.1f", ((info.rss*PAGESIZE) / (1024*1.0) / mon_total_mem) * 100.0); /* PFAULT STAT LCPU VSZ RSS */ plist->procs[k].page_fault = info.majflt; plist->procs[k].state=info.state; plist->procs[k].last_cpu = info.processor; plist->procs[k].vsize = info.vsize / 1024; plist->procs[k].rss = info.rss * PAGESIZE/1024; /* UTIME STIME */ sprintf(plist->procs[k].usr_time, "%.2f", info.utime*1.0 / Hertz); sprintf(plist->procs[k].sys_time, "%.2f", info.stime*1.0 / Hertz); /* COMMAND CWD EXE */ strcpy(plist->procs[k].command, info.comm); strcpy(plist->procs[k].cwd, cwd); strcpy(plist->procs[k].exe, exe); /* TIME */ plist->procs[k].time_lasting.day = day; plist->procs[k].time_lasting.hour = hour; plist->procs[k].time_lasting.minute = minute; plist->procs[k].time_lasting.second = second; } globfree(&globbuf); return plist; /* caller free */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -