如何在没有工具的情况下获得进程平均负载

如何在没有工具的情况下获得进程平均负载

我想在我的程序中列出进程及其信息。我可以从 /proc/[pid] 获得最多的信息。 top、htop等如何获取进程的平均负载?

答案1

加载系统的平均数量,是运行队列(即正在运行或等待运行)中的进程(线程)的平均数量(在 Linux 上进程处于不间断睡眠状态D如下状态)在某个时期内。

/proc/loadavg在 Linux 上,这在最后 1 分钟、5 分钟和 15 分钟内可用。

要查看当前这些线程(至少在ps读取相应/proc/pid/task/tid/stat文件时)是什么,您可以执行以下操作:

ps -eLo state,tid,args | awk '$1 ~ [RD]'

或者:

grep -ho '.*) [RD]' /proc/[1-9]*/task/*/stat

(作为近似值,假设进程名称不包含换行符或)字符。为了正确起见,对于第三个字段及以上字段,您需要从)文件中最后一次出现的位置开始)。

进程的负载确实没有意义,您可能想到的是 CPU 在一段时间内运行该进程所花费的时间。

例如,top每 1.5 秒打印一页,当进程的 %CPU 显示 300% 时,这意味着自打印最后一页以来的 1.5 秒内,CPU 已运行该进程的任务/线程总计 4.5秒。

要获取该信息,请获取周期开始和结束时(请参阅详细信息)的utime(14) 和stime(15) 字段的总和,并获取差值与持续时间的比率。/proc/pid/statman 5 proc

例如,与zsh

zmodload zsh/zselect
period=100 # centi-seconds
((clk_tck = $(getconf CLK_TCK)))
for i (1 2) {
  read -rd '' stat < /proc/$pid/stat;
  t[i]=$((${(j:+:)${(s: :)stat##*\)}[12,13]}))
  ((i == 2)) || zselect -t $period
}
printf '%.4g%%\n' $(((t[2] - t[1]) * 100. * 100 / period / clk_tck))

如果通过过程负载,您的意思是运行队列中该进程的平均线程数(根据@Patrick在评论中建议的定义),您可以通过获取一些示例来获得近似值,例如:

$ (repeat 100 grep -l ') [RD]' /proc/$pid/task/*/stat)|awk 'END{print NR/100}'
16.57

在运行这 100 个命令所花费的时间内,$pid运行队列中平均有 16.57 个线程。

答案2

对于系统范围的平均负载(和一些其他统计数据),请检查proc/loadavg。前三个字段是 1 分钟、5 分钟和 15 分钟的平均负载,这是大多数系统监视器显示的内容。第四个字段由两个用斜杠分隔的数字组成,第一个是可运行进程的数量,第二个是进程总数(包括线程)。第五个字段是系统上最新进程的PID。

如果你想要更详细的统计数据,你必须通过 netlink 与内核对话(不是特别容易),或者扫描编号目录/proc(由于 TOCTOU 竞争而不可靠)。您想要的相关文件可能是/proc/<PID>/stat,其中包含大多数任务管理器显示的大部分其他信息。确切的解释在这里发布有点长,但在 proc 文件系统的手册页(man proc在终端中)中已经很好地介绍了。

值得注意的是,“加载”在进程的上下文中没有意义。平均负载是在给定时间段内处于可运行状态的进程的平均数量(这是衡量系统繁忙程度的一个非常蹩脚的衡量标准,但那是另一个故事了),因此根据定义,给定的进程不能有一个“负载”值。进程在系统上生成负载,但它们本身没有“负载”。与此最接近的是进程使用的 CPU 时间量,这很容易通过 pollinb 上述文件来计算(Stéphane Chazelas 的答案涵盖了如何很好地计算它,所以我不会在这里重复) 。

相关内容