debian12 top -H 显示 CPU 利用率异常
问题环境现象
环境: debian12 (kernel 6.1.0)
现象: 运行一个多线程程序(测试程序见文末), 其中主线程空闲, 2个子线程繁忙, 使用 top -H 观察其各个线程的 CPU 利用率
可见, 此刻限制的主线程的 CPU 利用率异常地高.
原因分析
top
命令来自于procps-ng
包, 它通过定时读取/proc/PID
文件系统下内核暴露的 tick 数据, 计算 CPU 利用率.
如果不使用-H
选项, 则读取的就是整个进程(或者说线程组thread group)的占用近况, 此时读取的文件是/proc/[PID]/stat
如果使用-H
选项指定 PID, 则其会读取该 PID 内所有线程(task)的统计数据, 路径为 /proc/[PID]/task/[pid]/stat
比如在我们的例子中, 我们使用以下命令每隔1s读取整个线程组的统计数据
watch -n 1 "cat /proc/10179/stat"
结果为
可以观察到, 红框中标注的数据差不多每次变化200, 说明整个进程的 CPU 占用率应该为 200%. 这也符合 top -p
显示的结果
接下来通过以下命令, 查看各个线程的统计信息
watch -n 1 "cat /proc/10179/task/10179/stat;cat /proc/10179/task/10180/stat;cat /proc/10179/task/10181/stat"
结果为
可以观察到, 只有下面两行红框中标注的数据每次变化差不多100, 而首行几乎不变, 但这与使用 top -H -p 10179
的结果不符
因此, 问题到这里原因很明显了: 该系统自带的top
命令实现错了
由于procps-ng
是开源代码, 我们可以比较顺利地找到问题引入和修复的版本:
引入版本: https://gitlab.com/procps-ng/procps/-/commit/a37526260917bac624ae6b75fd9f4ea7287d81ad
修复版本: https://gitlab.com/procps-ng/procps/-/commit/bc688d630aeeeda5e003d35bbcfcdba08f21b399
附录
本文使用的测试程序如下:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
void *tfn(void *arg)
{
int a = 0;
while (1) {
a++;
}
return (void*)0;
}
int main()
{
pthread_t tid;
int i = 0;
printf("main--pid=%d,tid=%lu\n",getpid(),pthread_self());
for (; i < 2; i++){
int ret=pthread_create(&tid,NULL,tfn,NULL);
if(ret!=0){
fprintf(stderr,"pthread_create error:%s\n",strerror(ret));
exit(1);
}
}
sleep(6000);
return 0;
}