top 里显示的 CPU 百分比计算方式
top 看到的 CPU 信息解释的不是很清晰,就看下源码怎么写的吧。
程序很简单,基本都在 top.c 里。
load里的cpu详细信息代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14smpcpu = cpus_refresh(smpcpu);
if (CHKw(Curwin, View_CPUSUM)) {
// display just the 1st /proc/stat line
summaryhlp(&smpcpu[Cpu_tot], "Cpu(s):");
} else {
int i;
char tmp[SMLBUFSIZ];
// display each cpu's states separately
for (i = 0; i < Cpu_tot; i++) {
snprintf(tmp, sizeof(tmp), "Cpu%-3d:", smpcpu[i].id);
summaryhlp(&smpcpu[i], tmp);
}
}
Cpu_tot
为 CPU 数量。
cpus_refresh
函数里从 /proc/stat 文件里读入 CPU 信息,然后装入 smpcpu
里。smpcpu
为大小为 Cpu_tot+1
个 CPU_t
成员的数组。
/proc/stat文件的头几行为:1
2
3
4
5
6
7cpu %d %d ...
cpu0 %d %d ...
cpu1 %d %d ...
...
第一行的 CPU 信息装入 smpcpu[Cpu_tot]
,之后的 cpu0cpu1… 装入 smpcpu[0]\smpcpu[1\...
。
View_CPUSUM
这个由 1 键来控制的那个开关,开关关闭时只显示 smpcpu
的 Cpu_tot
,开关开启时显示的是 smpcpu
的下标 0~Cpu_tot-1
的成员。即,top 的默认在开头显示的 CPU 详细信息显示的是 /proc/stat 的第一行处理后,按下 1 键,显示的时 /proc/stat 后续各 CPU 数据。
/proc/stat 里都是数字,下边看看 top 里显示的百分比怎么算的。
CPU_t
的定义:1
2
3
4
5
6
7
8
9
10
11
12// These typedefs attempt to ensure consistent 'ticks' handling
typedef unsigned long long TIC_t;
typedef long long SIC_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, z; // as represented in /proc/stat
TIC_t u_sav, s_sav, n_sav, i_sav, w_sav, x_sav, y_sav, z_sav; // in the order of our display
unsigned id; // the CPU ID number
} CPU_t;
每次从 /proc/stat 取的数据称为一帧的数据,会从到 CPU_t
结构体的第一行成员里,上次的数据即上一帧的数据就拷到 CPU_t
的第二排带 _sav
后缀的成员里,一一对应。
summaryhlp
函数里计算我们想看的 CPU 各详细指标的百分比。只取部分代码或伪码做演示:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15SIC_t u_frme, s_frme, n_frme, i_frme, w_frme, x_frme, y_frme, z_frme, tot_frme, tz;
float scale;
u_frme = cpu->u - cpu->u_sav;
s_frme = cpu->s - cpu->s_sav;
...
tot_frme = u_frme + s_frme + n_frme + i_frme + w_frme + x_frme + y_frme + z_frme;
if (tot_frme < 1) tot_frme = 1;
scale = 100.0 / (float)tot_frme;
us% = (float)u_frme * scale;
sy% = (float)s_frme * scale;
...
cpu->u_sav = cpu->u;
cpu->s_sav = cpu->s;
...
每个进程占cpu百分比计算:1
2
3Frame_tscale = 100.0f / ((float)Hertz * (float)et * (Rc.mode_irixps ? 1 : Cpu_tot));
float u = (float)p->pcpu * Frame_tscale;
算的是两帧之间总时间片数量,各进程占的时间片数量百分比。