/* here are no errors and it can run normally */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#define CPU_INFO_SIZE 1024
#define SLEEP 3
/*
#define STATES_line2x4 "%s/03" /
" %#5.1f%% /02user,/03 %#5.1f%% /02system,/03 %#5.1f%% ,nice : %#5.1f%% /02idle/03/n"
*/
#define STATES_line2x4 "%s ," /
" user: %#5.1f%% , system: %#5.1f%% , idle: %#5.1f%% /n"
static const char *States_fmts = STATES_line2x4;
//Total number of CPU
static int Cpu_tot;
// These typedefs attempt to ensure consistent 'ticks' handling
typedef unsigned long long TIC_t;
// This structure stores a frame's cpu tics used in history
// calculations. It exists primarily for SMP support but serves
// all environments.
typedef struct CPU_t {
TIC_t u, n, s, i, w, x, y; // as represented in /proc/stat
TIC_t u_sav, s_sav, n_sav, i_sav, w_sav, x_sav, y_sav; // in the order of our display
unsigned id; // the CPU ID number
} CPU_t;
// This routine simply formats whatever the caller wants and
// returns a pointer to the resulting 'const char' string...
static const char *fmtmk (const char *fmts, ...)
{
static char buf[2048]; // with help stuff, our buffer
va_list va; // requirements exceed 1k
va_start(va, fmts);
vsnprintf(buf, sizeof(buf), fmts, va);
va_end(va);
return (const char *)buf;
}
/* refresh cpu information */
static CPU_t *cpus_refresh (CPU_t *cpus)
{
static FILE *fp = NULL;
int i;
int num;
// enough for a /proc/stat CPU line (not the intr line)
char buf[256+64];
if (!fp) {
if (!(fp = fopen("/proc/stat", "r")))
printf("Failed /proc/stat open: %s", strerror(errno));
//cpus = calloc(1, (1 + Cpu_tot) * sizeof(CPU_t));
cpus = (CPU_t *)malloc((1 + Cpu_tot) * sizeof(CPU_t));
memset(cpus, '/0', (1 + Cpu_tot) * sizeof(CPU_t));
}
rewind(fp);
fflush(fp);
// first value the last slot with the cpu summary line
if (!fgets(buf, sizeof(buf), fp))
printf("failed /proc/stat read/n");
cpus[Cpu_tot].x = 0; // FIXME: can't tell by kernel version number
cpus[Cpu_tot].y = 0; // FIXME: can't tell by kernel version number
num = sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
&cpus[Cpu_tot].u,
&cpus[Cpu_tot].n,
&cpus[Cpu_tot].s,
&cpus[Cpu_tot].i,
&cpus[Cpu_tot].w,
&cpus[Cpu_tot].x,
&cpus[Cpu_tot].y
);
if (num < 4)
printf("failed /proc/stat read/n");
// and just in case we're 2.2.xx compiled without SMP support...
if (Cpu_tot == 1) {
cpus[1].id = 0;
memcpy(cpus, &cpus[1], sizeof(CPU_t));
}
// now value each separate cpu's tics
for (i = 0; 1 < Cpu_tot && i < Cpu_tot; i++) {
if (!fgets(buf, sizeof(buf), fp))
printf("failed /proc/stat read/n");
cpus[i].x = 0; // FIXME: can't tell by kernel version number
cpus[i].y = 0; // FIXME: can't tell by kernel version number
num = sscanf(buf, "cpu%u %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
&cpus[i].id,
&cpus[i].u, &cpus[i].n, &cpus[i].s, &cpus[i].i, &cpus[i].w, &cpus[i].x, &cpus[i].y
);
if (num < 4)
printf("failed /proc/stat read/n");
}
return cpus;
}
/* get cpu use information */
char * summaryhlp (int cpu_n,CPU_t *cpu, const char *pfx)
{
// we'll trim to zero if we get negative time ticks,
// which has happened with some SMP kernels (pre-2.4?)
#define TRIMz(x) ((tz = (long long)(x)) < 0 ? 0 : tz)
long long u_frme, s_frme, n_frme, i_frme, w_frme, x_frme, y_frme, tot_frme, tz;
float scale;
char information[1024] = {0};
if(cpu == NULL){
printf("NULL@/n");
return;
}
/*printf("u = %Lu, u_sav = %Lu/n", cpu->u, cpu->u_sav);*/
u_frme = cpu->u - cpu->u_sav;
s_frme = cpu->s - cpu->s_sav;
n_frme = cpu->n - cpu->n_sav;
i_frme = TRIMz(cpu->i - cpu->i_sav);
w_frme = cpu->w - cpu->w_sav;
x_frme = cpu->x - cpu->x_sav;
y_frme = cpu->y - cpu->y_sav;
tot_frme = u_frme + s_frme + n_frme + i_frme + w_frme + x_frme + y_frme;
if (tot_frme < 1) tot_frme = 1;
scale = 100.0 / (float)tot_frme;
/*printf("scale = %0.5f/n", scale);*/
// display some kinda' cpu state percentages
// (who or what is explained by the passed prefix)
char cpu_num[6];
char u_val[6];
char s_val[6];
char i_val[6];
float cpu_number = (float)cpu_n;
float u_use = (float)(u_frme + x_frme + y_frme)* scale;
float s_use = (float)s_frme * scale;
float i_use = (float)i_frme * scale;
sprintf(cpu_num,"%.2f",cpu_number);
sprintf(u_val,"%.2f",u_use);
sprintf(s_val,"%.2f",s_use);
sprintf(i_val,"%.2f",i_use);
strcat(information," CPU number: ");
strcat(information,cpu_num);
strcat(information," Cpu(s), User: ");
strcat(information,u_val);
strcat(information," /% , System: ");
strcat(information,s_val);
strcat(information," /% , Idle: ");
strcat(information,i_val);
strcat(information," /% .");
/*printf("%s",information);*/
// remember for next time around
cpu->u_sav = cpu->u;
cpu->s_sav = cpu->s;
cpu->n_sav = cpu->n;
cpu->i_sav = cpu->i;
cpu->w_sav = cpu->w;
cpu->x_sav = cpu->x;
cpu->y_sav = cpu->y;
#undef TRIMz
return information;
}
/* get all of cpu's information */
char * get_cpu_info()
{
static CPU_t * smpcpu = NULL;
char * cpu_informatin = NULL;
Cpu_tot = sysconf(_SC_NPROCESSORS_ONLN);
smpcpu = cpus_refresh(smpcpu);
cpu_informatin = summaryhlp(Cpu_tot,&smpcpu[Cpu_tot], " Cpu(s)");
return cpu_informatin;
}
/*当使用时只需掉用get_cpu_info即可得到CPU使用率,返回的为数组首地址*/