对于Linux系统,各种关于系统内核的活动信息都可以在/proc/stat文件中找到,该文件记录了自系统第一次启动以来的所有内核的相关数据,下面对文件内容各字段做一点说明:
这些数字指明了CPU执行不同的任务所消耗的时间(从系统启动开始累计到当前时刻)。时间单位是USER_HZ或jiffies(通常是百分之一秒)。
这些数据列的含义如下,我们从左至右逐一认识:
•user:正常的进程在用户态下执行时间累积
•nice: NICED的进程在用户态下执行时间列
•system:进程在内核态的执行时间累积
•idle:空闲时间累积
•iowait :等待I / O完成时间累积
•irq :硬中断时间
•softirq:软中断时间
"intr":这行给出自系统启动以来的所有中断信息。第一个数字记录所有的中断的次数;然后每个数对应一个特定的中断自系统启动以来所发生的次数。
"ctxt":给出了自系统启动以来CPU发生的上下文交换的次数。
"btime":给出了从系统启动到现在为止的时间,单位为秒。
"processes (total_forks)":自系统启动以来所创建的任务的个数目。
"procs_running":当前运行队列的任务的数目。
"procs_blocked":当前被阻塞的任务的数目,等待I/O完成次数。
统计cpu利用率
typedef struct CPU_PACKED
{
char name[20];
uint32_t user;
uint32_t nice;
uint32_t system;
uint32_t idle;
}CPU_OCCUPY;
float cal_cpuoccupy(CPU_OCCUPY* o, CPU_OCCUPY* n)
{
uint64_t od, nd;
uint64_t id, sd;
float cpu_use = 0;
od = (uint64_t)(o->user + o->nice + o->system + o->idle);
nd = (uint64_t)(n->user + n->nice + n->system + n->idle);
id = (uint64_t)(n->user - o->user);
sd = (uint64_t)(n->system - o->system);
if ((nd - od) != 0)
cpu_use = (float)((sd + id) * 100) / (nd - od);
else
cpu_use = 0;
return cpu_use;
}
void get_cpuoccupy(CPU_OCCUPY* cpust)
{
FILE* fd = NULL;
int n;
char buf[256];
CPU_OCCUPY* cpu_occupy;
cpu_occupy = cpust;
fd = fopen("/proc/stat", "r");
if (!fd)
return;
fgets(buf, sizeof(buf), fd);
sscanf(buf, "%s %u %u %u %u", cpust->name, &cpust->user,
&cpust->nice, &cpust->system, &cpust->idle);
fclose(fd);
}
float get_cpurate()
{
CPU_OCCUPY cpu_stat1 = { 0 };
CPU_OCCUPY cpu_stat2 = { 0 };
float cpu = -1;
// 第一次获取cpu使用情况
get_cpuoccupy(&cpu_stat1);
if (!cpu_stat1.user)
return -1;
sleep(1);
//第二次回去cpu使用情况
get_cpuoccupy(&cpu_stat2);
if (!cpu_stat2.user)
return -1;
//结算使用率
cpu = cal_cpuoccupy(&cpu_stat1, &cpu_stat2);
return cpu;
}
更进一步如果需要查看各进程的cpu使用情况那么就需要查看/proc/数字(pid)/stat文件了,原理同上。
统计内存使用情况:
统计内存信息就需要使用/proc/meminfo文件了,下面是该文件的一段截图:
//获取内存相关信息
typedef struct MEM_PACKED
{
char name[20];
uint32_t total;
char anme2[20];
}MEM_OCCUPY;
typedef struct MEM_PACK
{
float total;
float used_rate;
}MEM_PACK;
MEM_PACK get_memoccupy()
{
FILE* fd;
int n;
float mem_total, mem_used_rate;
char buff[256];
MEM_OCCUPY* mem = (MEM_OCCUPY*)new MEM_OCCUPY;
MEM_PACK mem_pack;
fd = fopen("/proc/meminfo", "r");
memset(buff, 0, sizeof(buff));
fgets(buff, sizeof(buff), fd);
sscanf(buff, "%s %lu %s\n", mem->name, &mem->total, mem->anme2);
mem_total = mem->total;
fgets(buff, sizeof(buff), fd);
memset(buff, 0, sizeof(buff));
fgets(buff, sizeof(buff), fd);
sscanf(buff, "%s %lu %s\n", mem->name, &mem->total, mem->anme2);
mem_used_rate = (1 - mem->total / mem_total) * 100;
mem_pack.total = mem_total;
mem_pack.used_rate = mem_used_rate;
fclose(fd);
delete mem;
}
获取进程相关的信息:
typedef struct Proc {
int pid;
int ppid;
int uid;
int euid;
int gid;
char item_state;
long item_cutime;
long item_cstime;
long item_rss;
int item_threads;
unsigned long item_utime;
unsigned long item_stime;
unsigned long long item_starttime;
uint64_t read_bytes;
uint64_t write_bytes;
char name[4096];
char secattr[STRLEN];
} Proc, *Proc_T;
typedef enum {
ProcessEngine_None = 0x0,
ProcessEngine_CollectCommandLine = 0x1
} __attribute__((__packed__)) ProcessEngine_Flags;
bool file_readProc(char* buf, int buf_size, char* name, int pid, int* bytes_read)
{
if (!buf || !name)
return false;
char filename[STRLEN];
if (pid < 0)
snprintf(filename, sizeof(filename), "/proc/%s", name);
else
snprintf(filename, sizeof(filename), "/proc/%d/%s", pid, name);
int fd = open(filename, O_RDONLY);
if (fd < 0) {
return false;
}
bool rv = false;
int bytes = (int)read(fd, buf, buf_size - 1);
if (bytes >= 0) {
if (bytes_read)
*bytes_read = bytes;
buf[bytes] = 0;
rv = true;
}
else {
*buf = 0;
}
close(fd);
return rv;
}
static bool _parseProcPidStat(Proc_T proc)
{
char buf[4096];
char* tmp = NULL;
if (!file_readProc(buf, sizeof(buf), "stat", proc->pid, NULL)) {
return false;
}
if (!(tmp = strrchr(buf, ')'))) {
return false;
}
*tmp = 0;
if (sscanf(buf, "%*d (%255s", proc->name) != 1) {
return false;
}
tmp += 2;
if (sscanf(tmp,
"%c %d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu %ld %ld %*d %*d %d %*u %llu %*u %ld %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*d %*d\n",
&(proc->item_state),
&(proc->ppid),
&(proc->item_utime),
&(proc->item_stime),
&(proc->item_cutime),
&(proc->item_cstime),
&(proc->item_threads),
&(proc->item_starttime),
&(proc->item_rss)) != 9) {
return false;
}
return true;
}
static bool _parseProcPidStatus(Proc_T proc)
{
char buf[4096];
char* tmp = NULL;
if (!file_readProc(buf, sizeof(buf), "status", proc->pid, NULL)) {
return false;
}
if (!(tmp = strstr(buf, "Uid:"))) {
return false;
}
if (sscanf(tmp + 4, "\t%d\t%d", &(proc->uid), &(proc->euid)) != 2) {
return false;
}
if (!(tmp = strstr(buf, "Gid:"))) {
return false;
}
if (sscanf(tmp + 4, "\t%d", &(proc->gid)) != 1) {
return false;
}
return true;
}
获取磁盘使用情况:
#include <stdio.h>
#include <sys/statvfs.h>
#define SYSTEM_BITS 64
#define PATH "/"
#define KB 1024
#define MB 1024*1024
#define GB 1024*1024*1024
int main(void)
{
int state;
struct statvfs vfs;
fsblkcnt_t block_size = 0;
fsblkcnt_t block_count = 0;
fsblkcnt_t total_size;
fsblkcnt_t free_size;
fsblkcnt_t used_size;
fsblkcnt_t avail_size;
state = statvfs(PATH, &vfs);
if (state < 0) {
return 0;
}
/* 获取一个block的大小 */
block_size = vfs.f_bsize;
/* 获取总容量 */
total_size = vfs.f_blocks * block_size;
/* 获取可用容量 */
free_size = vfs.f_bfree * block_size;
/* 获取使用容量 */
used_size = (vfs.f_blocks - vfs.f_bavail) * block_size;
/* 获取有效容量 */
avail_size = vfs.f_bavail * block_size;
printf("total_size = %0.2lf GB\n", (double)total_size / (GB));
printf("free_size = %0.2lf GB\n", (double)free_size / (GB));
printf("used_size = %0.2lf GB\n", (double)used_size / (GB));
printf("avail_size = %0.2lf GB\n", (double)avail_size / (GB));
return 0;
}
参考: