您的位置:首页 > 运维架构 > Linux

linux 获取 CPU 使用信息

2015-10-11 11:20 453 查看
在 Shell 脚本中,我们可以通过 top -n 1 来获取,获取内容如下:



具体参数的意思在这里不做解释,我们主要看一下用 C 代码如何获取 CPU 的使用信息,达到命令 top 的目的。

先来了解一下内核维护的一个借口 /proc/stat 这个文件,使用命令 cat /proc/stat 得到内容如下:



cpu 一行从左到右参数的意思依次是(单位:jiffies):

jiffies 是内核中的一个全局变量,用来记录自系统启动以来产生的节拍数,在 linux 中,一个节拍数大致可以理解为操作系统进程调度的最小时间片,不同 linux 内核可能值有不同,通常在 1ms 到 10ms 之间。

user(103769):从系统启动开始累积到当前时刻,处于用户态的运行时间,不包含 nice 值为负进程的运行时间。

nice(0):从系统启动开始累计到当前时刻,nice 值为负的进程所占用的 CPU 时间。

system(164913):从系统启动开始累计到当前时刻,处于内核态的运行时间。

idle(1503325):从系统启动开始累计到当前时刻,除 IO 等待时间以外的其它等待时间。

iowait(0):从启动启动开始累计到当前时刻,IO 等待时间。(版本 2.5.41 后)

irq(0):从系统启动开始累计到当前时刻,硬中断时间。(版本 2.6.0 后)

softirq(15396):从系统启动开始累计到当前时刻,软中断时间。(版本 2.6.0 后)

stealstolen(0):which is the time spent in other operating systems when running in a virtualized environment.

guest (0):which is the time spent running a virtual CPU for guest operating systems under the control of the Linux kernel.(版本 2.6.24 后)

总体运行时间:TotalCPUTime = user + nice + idle + iowait + irq + softirq + stealstolen + guest。

CPU 运行时间:UserCPUTime = TotalCPUTime - idle - iowait

C 代码实现:

// CPU 信息结构体typedef struct cpu
{
unsigned long long USR;
unsigned long long NIC;
unsigned long long SYS;
unsigned long long IDLE;
unsigned long long IOWAIT;
unsigned long long IRQ;
unsigned long long SOFTIRQ;
unsigned long long STEAL;
unsigned long long TOTAL;
unsigned long long USAGE;

double BOGOMIPS;
}CPU_INFO;
// 读取 CPU 信息static inline int readCpuInfo(CPU_INFO *cpu){
if ( NULL == cpu )
{
write_log("The parameter is NULL.");
return -1;
}
const char fmt[] = "cpu %llu %llu %llu %llu %llu %llu %llu %llu";
char line[LINE_LEN];
bzero(line, LINE_LEN);

FILE *stat = OPEN_FILE("/proc/stat", "r");
if (!fgets(line, LINE_LEN, stat) || line[0] != 'c' )
{
close(stat);
write_log("Read CPU infonation failed.");
return -1;
}
close(stat);

int ret = sscanf(line, fmt, cpu->USR, cpu->NIC, cpu->SYS,
cpu->IDLE, cpu->IOWAIT, cpu->IRQ, cpu->SOFTIRQ, cpu->STEAL);
if (ret >= 4)
{
cpu->TOTAL = cpu->USR + cpu->NIC + cpu->SYS + cpu->IDLE + cpu->IOWAIT
+ cpu->IRQ + cpu->SOFTIRQ + cpu->STEAL;
cpu->USAGE = cpu->TOTAL - cpu->IDLE - cpu->IOWAIT;
}
return ret;
}

// 通过 CPU 使用时间计算 CPU 的使用率
int getCpuUsageRates()
{
double usage = 0;
CPU_INFO pre_cpu;

if ( 4 > readCpuInfo(&pre_cpu) )
{
write_log("Get CPU info failed.");
return -1;
}

usleep(100000);

CPU_INFO cur_cpu;
if ( 4 > readCpuInfo(&cur_cpu) )
{
write_log("Get CPU info failed.");
return -1;
}

usage = (cur_cpu.USAGE - pre_cpu.USAGE)/(cur_cpu.TOTAL - pre_cpu.TOTAL) * 100;
return usage;
}


扩展:

一、获取进程使用 CPU 率,/proc/<pid>/stat 文件

该文件包含了某一进程所有的活动的信息,该文件中的所有值都是从系统启动开始累计到当前时刻。以下通
过实例数据来说明该文件中各个字段的含义。下面我们来看一下4081这个进程的详细信息:



从左到右各列的具体信息如下:
pid=4081
进程号
comm=atd
应用程序或者命令的名字
task_state=S
任务状态,R:running;S:sleeping;D:dist sleep;T:stop;T:tracing stop;Z:zombie;X:dead
ppid=1
父进程 ID
pgid=4081
线程组号
sid=4081
该进程所在的会话组 ID
tty_nr=0
该任务的tty终端的设备号,
tty_pgrp=-1
终端的进程组号,当前运行在该任务所在终端的前台任务
task->flags=4194624
进程标志位,查看该任务的特性
min_fit=93
该任务不需要从硬盘拷数据而发生的缺页(次缺页)的次数
cmin_fit=0
累计的改任务的所有的waited-fon进程曾经发生的次缺页的次数目
maj_fit=0
该任务需要从硬盘拷数据而发生的缺页(主缺页)的此数目
cmaj_fit=0
累计的该任务的所有的 waited-fon 进程曾经发生的主缺页的此数目
utime=0
该任务在用户态运行的时间,单位为 jiffies
stime=0
该任务在内核态运行的时间,单位为 jiffies
cutime=0
累计的该任务的所有的 waited-fon 进程曾经在用户态运行的时间,单位为 jiffies
cstime=0
累计的该任务的所有的 waited-fon 进程曾近在内核态运行的时间,单位为 jiffies
priority=18
任务的动态优先级
nice=0
任务的静态优先级
num_threads=1
该任务所在的线程组里的线程的个数
it_real_value=0
由于计算时间间隔导致的下一个 SIGALRM 发送进程的时延,以 jiffies 为单位
start_time=4449
该任务的启动时间大小,单位为 jiffies
vsize=2318336
该任务的虚拟地址空间大小
rss=111
该任务当前驻留物理地址空间的大小
rlim=4294967295
该任务驻留物理地址空间的最大值,单位为 bytes
start_code=3461120
该任务在虚拟地址空间的代码段的起始地址
end_code=3479704
该任务在虚拟地址空间的代码段的结束地址
start_stack=3215230176
该任务在虚拟地址空间栈的结束地址
kstkesp=3215229372
esp
(32 位堆栈指针) 的当前值, 与在进程的内核堆栈页得到的一致.
kstkeip=5280784
指向将要执行的指令的指针, EIP(32 位指令指针)的当前值.
pendingsig=0
待处理信号的位图,记录发送给进程的普通信号
block_sig=0
阻塞信号的位图
sigign=0
忽略的信号的位图
sigcatch=819
23 被俘获的信号的位图
wchan=0
如果该进程是睡眠状态,该值给出调度的调用点
nswap=0
被swapped的页数,当前没用
cnswap=0
所有子进程被swapped的页数的和,当前没用
exit_signal=17
该进程结束时,向父进程所发送的信号
task_cpu(task)=0
运行在哪个CPU上
task_rt_priority=0
实时进程的相对优先级别
task_policy=0
进程的调度策略,0=非实时进程,1=FIFO实时进程;2=RR实时进程

进程的总Cpu时间processCpuTime
= utime + stime + cutime + cstime,该值包括其所有线程的cpu时间

总的 CPU 使用率计算
计算方法:
1、采样两个足够短的时间间隔的Cpu快照,分别记作t1,t2,其中t1、t2的结构均为:
(user、nice、system、idle、iowait、irq、softirq、stealstolen、guest)的9元组;
2、计算总的Cpu时间片totalCpuTime
a) 把第一次的所有cpu使用情况求和,得到s1;
b) 把第二次的所有cpu使用情况求和,得到s
c) s2
- s1得到这个时间间隔内的所有时间片,即totalCpuTime = j2 - j1
;
3、计算空闲时间idle
idle对应第四列的数据,用第二次的第四列 - 第一次的第四列即可
idle=第二次的第四列 - 第一次的第四列
4、计算cpu使用率
pcpu =100* (total-idle)/total

某一进程 CPU 的使用率
计算方法:
1、 采样两个足够短的时间间隔的cpu快照与进程快照,
a) 每一个cpu快照均为(user、nice、system、idle、iowait、irq、softirq、stealstolen、guest)的9元组
b)
每一个进程快照均为 (utime、stime、cutime、cstime)的4元组;
2、分别根据结论2、结论3计算出两个时刻的总的cpu时间与进程的cpu时间,分别
作:totalCpuTime1、totalCpuTime2、processCpuTime1、processCpuTime2
3、计算该进程的cpu使用率
pcpu
= 100*( processCpuTime2 – processCpuTime1) / (totalCpuTime2 – totalCpuTime1)
(按100%计算,如果是多核情况下还需乘以cpu的个数)

参考博客:http://www.blogjava.net/fjzag/articles/317773.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: