这个问题已经被问过很多次了,但是我找不到一个得到充分支持的答案.

许多人建议使用top命令,但如果您运行top一次(因为您有一个脚本,例如每1秒收集一次Cpu使用情况),它将始终给出相同的Cpu使用情况结果(example 1example 2).

计算CPU使用率的更准确方法是读取/proc/stat中的值,但大多数答案只使用/proc/stat中的前4个字段来计算CPU使用率(一个示例here).

从Linux内核2.6.33开始,/proc/stat/每个CPU核心有10个字段!

我还发现了这Accurately Calculating CPU Utilization in Linux using /proc/stat个问题,它指出了同样的问题——大多数其他问题只考虑了众多领域中的4个领域——但这里给出的答案仍然以"我认为"(不确定)开头,除此之外,它只关注前7个领域(/proc/stat/中的10个领域)

This perl脚本使用所有字段来计算CPU使用率,经过进一步调查后,我认为这也是不正确的.

在快速查看内核代码here之后,例如,guest_niceguest fields总是与niceuser一起增加(因此它们不应该包括在cpu使用率计算中,因为它们已经包含在niceuser字段中)

/*
 * Account guest cpu time to a process.
 * @p: the process that the cpu time gets accounted to
 * @cputime: the cpu time spent in virtual machine since the last update
 * @cputime_scaled: cputime scaled by cpu frequency
 */
static void account_guest_time(struct task_struct *p, cputime_t cputime,
                   cputime_t cputime_scaled)
{
    u64 *cpustat = kcpustat_this_cpu->cpustat;

    /* Add guest time to process. */
    p->utime += cputime;
    p->utimescaled += cputime_scaled;
    account_group_user_time(p, cputime);
    p->gtime += cputime;

    /* Add guest time to cpustat. */
    if (task_nice(p) > 0) {
        cpustat[CPUTIME_NICE] += (__force u64) cputime;
        cpustat[CPUTIME_GUEST_NICE] += (__force u64) cputime;
    } else {
        cpustat[CPUTIME_USER] += (__force u64) cputime;
        cpustat[CPUTIME_GUEST] += (__force u64) cputime;
    }
}

总之,在Linux中,计算CPU使用率的准确方法是什么?计算中应该考虑哪些字段,以及如何计算(哪些字段归因于空闲时间,哪些字段归因于非空闲时间)?

推荐答案

根据htop个源代码,我的假设似乎是有效的:

(参见第LinuxProcessList.c页的static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this)功能)

// Guest time is already accounted in usertime
usertime = usertime - guest;                             # As you see here, it subtracts guest from user time
nicetime = nicetime - guestnice;                         # and guest_nice from nice time
// Fields existing on kernels >= 2.6
// (and RHEL's patched kernel 2.4...)
unsigned long long int idlealltime = idletime + ioWait;  # ioWait is added in the idleTime
unsigned long long int systemalltime = systemtime + irq + softIrq;
unsigned long long int virtalltime = guest + guestnice;
unsigned long long int totaltime = usertime + nicetime + systemalltime + idlealltime + steal + virtalltime;

因此,从/proc/stat的第一行中列出的字段中:(参见第1.8节第documentation页)

     user    nice   system  idle      iowait irq   softirq  steal  guest  guest_nice
cpu  74608   2520   24433   1117073   6176   4054  0        0      0      0

在算法上,我们可以计算CPU使用率百分比,如下所示:

PrevIdle = previdle + previowait
Idle = idle + iowait

PrevNonIdle = prevuser + prevnice + prevsystem + previrq + prevsoftirq + prevsteal
NonIdle = user + nice + system + irq + softirq + steal

PrevTotal = PrevIdle + PrevNonIdle
Total = Idle + NonIdle

# differentiate: actual value minus the previous one
totald = Total - PrevTotal
idled = Idle - PrevIdle

CPU_Percentage = (totald - idled)/totald

Linux相关问答推荐

是否可以在Bash正则表达式中排除?

Azure Linux B1s VM-Jenkins Sever已安装,但主页未打开

cu可以从串口读取,但我自己的C程序不能

动态链接ELF文件是否需要ELF节头表?

如何在 gcc 搜索路径上防止多个版本的 Boost?

什么命令用于在linux中创建或修改具有指定文件大小的多个文件

访问证书里面的图片

nohup 是否可以跨管道工作?

用于判断进程是否正在运行并对结果采取行动的 Linux 脚本

Linux C程序:如何找到函数所属的库

如何告诉 valgrind 对Forking 进程进行 memcheck?

如何在不重新打印的情况下更新终端中的打印消息

如何列出附加到Linux中共享内存段的进程?

docker images显示图像,docker rmi表示没有这样的图像或参考不存在

如果关键字触发然后执行命令,Shell 脚本来监视日志(log)文件?

从 FTP 服务器下载所有文件

Docker:您是否try 连接到没有 TLS 的启用 TLS 的守护进程?

如何让我的 Golang Web 服务器在后台运行?

Linux 上的 NuGet:获取响应流时出错

Linux cmd 在 jar 中搜索类文件,而不考虑 jar 路径