Linux下C/C++实现cpustat(测量CPU利用率)

news2024/11/18 16:48:26

在Linux中,cpustat定期转储正在运行的进程的当前CPU利用率统计信息。cpustat已被优化为具有最小的CPU开销,与top相比,通常使用约35%的CPU。cpustat还包括一些简单的统计分析选项,可以帮助描述CPU的加载方式。

cpustat介绍

cpustat是一个转储当前运行任务(即进程或内核线程)的CPU利用率的程序。cpustat用于监视系统中长期存在的进程的活动,例如守护进程、内核线程以及典型的用户进程。

cpustat [ options ] [delay [count]]

cpustat命令行选项:

-h帮助

-a 基于所有CPU节拍而不是一个CPU来计算CPU利用率

-c 从进程命令字段获取命令名(CPU成本较低)

-d 删除目录basename命令信息

-D 显示运行结束时CPU利用率统计数据的分布

-g 显示运行结束时CPU利用率统计的总计

-i 忽略了统计数据中的cpustat

-l 显示长(完整)命令信息

-n 指定要显示的任务数

-q 安静运行,使用选项-r非常有用

-r 指定要将样本转储到的逗号分隔值输出文件。

-s 显示简短命令信息

-S 时间戳输出

-t 指定忽略小于此值的样本的任务刻度计数阈值。

-T 显示总CPU利用率统计数据

-x 显示额外的统计数据(平均负载、平均cpu频率等)

对于在采样时间内消耗了一些CPU的每个正在运行的任务,将显示以下信息:

标题说明
%CPU  使用的CPU总数(百分比)
%USR  空间中使用的USR CPU(百分比)
%SYS (内核)空间中使用的SYS CPU(百分比)
PID   进程ID
S进程状态,R(运行),S(休眠),D(等待,磁盘休眠),T(停止),T(跟踪停止),W(寻呼),X(死),X(死)、K(唤醒),W),P(停止)。
CPU采样时进程使用的CPU。
Time  自进程启动以来使用的CPU总时间。
Task  进程命令行信息(来自进程命令行或命令字段)


cpustat定期报告正在运行的任务的当前CPU利用率,并且可以在运行结束时报告每个CPU和每个任务的利用率统计信息。

cpustat工具实现的一些知识点

  • Linux 当前线程数查询


/proc/sys/kernel/pid_max #查系统支持的最大线程数,一般会很大,相当于理论值。

  • /proc/pid/cmdline :进程的命令行参数

该文件保存了进程的完整命令行. 如果该进程已经 被交换出内存, 或者该进程已经僵死, 那么就没有 任何东西在该文件里, 这时候对该文件的读操作将返回零 个字符. 该文件以空字符null 而不是换行符作为结 束标志.

  • /proc/stat: 计算cpu的利用率
stat   进程状态信息, 被命令 ps(1) 使用.

       现将该文件里各域, 以及他们的 scanf(3) 格式说明符, 按顺序分述如下:

       pid %d 进程标识.

       comm %s
              可执行文件的文件名, 包括路径. 该文件是否可 见取决于该文件是否已被交换出内存.

       state %c
              ";RSDZT"; 中的一个, R 是正在运行, S 是 在可中断的就绪态中睡眠, D 是在不可中 断的等待或交换态中睡眠, Z 是僵死, T 是被跟踪或被停止(由于收到信号).

       ppid %d
              父进程 PID.

       pgrp %d
              进程的进程组 ID.

       session %d
              进程的会话 ID.

       tty %d 进程所使用终端.

       tpgid %d
              当前拥有该进程所连接终端的进程所在的进程 组 ID.

       flags %u
              进程标志. 目前每个标志都设了数学位, 所以输出里就不包括该位. crt0.s 检查数学仿真 这可能是一个臭虫, 因为不是每个进 程都是用 c 编译的程序. 数学位应该是十 进制的
              4, 而跟踪位应该是十进制的 10.

       minflt %u
              进程所导致的小错误(minor faults)数目, 这样的 小错误(minor faults)不需要从磁盘重新载入一个 内存页.

       cminflt %u
              进程及其子进程所导致的小错误(minor faults)数目.

       majflt %u
              进程所导致的大错误(major faults)数目, 这样的 大错误(major faults)需要重新载入内存页.

       cmajflt %u
              进程及其子进程所导致的大错误(major faults)数目.

       utime %d
              进程被调度进用户态的时间(以 jiffy 为单 位, 1 jiffy=1/100 秒,另外不同硬件体系略有不同).

       stime %d
              进程被调度进内核态的时间, 以 jiffy 为 单位.

       cutime %d
              进程及其子进程被调度进用户态的时间, 以 jiffy 为单位.

       cstime %d
              进程及其子进程被调度进内核态的时间, 以 jiffy 为单位.

       counter %d
              如果进程不是当前正在运行的进程, 就是 进程在下个时间片当前可以拥有的最大时 间, 以 jiffy 为单位. 如果进程是当前正 在运行的进程, 就是当前时间片中所剩下 jiffy
              数目.

       priority %d
              标准优先数只再加上 15, 在内核里该值总 是正的.

       timeout %u
              当前至进程的下一次间歇时间, 以 jiffy 为单位.

       itrealvalue %u
              由于计时间隔导致的下一个 SIGALRM 发送进程的时延,以 jiffy 为单位.

       starttime %d
              进程自系统启动以来的开始时间, 以 jiffy 为单位.

       vsize %u
              虚拟内存大小.

       rss %u Resident Set Size(驻留大小): 进程所占用的真实内 存大小, 以页为单位, 为便于管理而减去 了 3. rss 只包括正文, 数据以及堆栈的空间,
              但不包括尚未要求装入内存的或已被交换出去的.

       rlim %u
              当前进程的 rss 限制, 以字节为单位, 通 常为 2,147,483,647.

       startcode %u
              正文部分地址下限.

       endcode %u
              正文部分地址上限.

       startstack %u
              堆栈开始地址.

       kstkesp %u
              esp(32 位堆栈指针) 的当前值, 与在进程 的内核堆栈页得到的一致.

       kstkeip %u
              EIP(32 位指令指针)的当前值.

       signal %d
              待处理信号的 bitmap(通常为 0).

       blocked %d
              被阻塞信号的 bitmap(对 shell 通常是 0, 2).

       sigignore %d
              被忽略信号的 bitmap.

       sigcatch %d
              被俘获信号的 bitmap.

       wchan %u
              进程在其中等待的通道, 实际是一个系统 调用的地址. 如果你需要文本格式的, 也 可以在名字列表中找到.  (如果有最新版本的 /etc/psdatabase, 你 可以在 ps -l 的结果中的
              WCHAN 域看到)

  • /sys/devices/system/cpu/cpu:获取平均CPU频率

查看CPU核心的当前运行频率,使用如下的命令


其中cpu0指第一个核心,根据情况可以换成cpu1, cpu2,cpu3…,在online文件里描述cpu的状态,0代表下线,1代表上线

  • /proc/loadavg : 获取当前负载平均状态


前三个数字是1、5、15分钟内的平均进程数(有人认为是系统负荷的百分比,其实不然,有些时候可以看到200甚至更多)。
第四个值的分子是正在运行的进程数,分母是进程总数,最后一个是最近运行的进程ID号。
这里的平均负载也就是可运行的进程的平均数。

  • ncurses:顶部模式下的设置显示
static void cpustat_top_setup(void)
{
	(void)initscr(); //屏幕就会初始化并进入curses 模式
	(void)cbreak(); //cbreak()函数都可以禁止行缓冲
	(void)noecho(); // 禁止输入的字符出现在屏幕上
	(void)nodelay(stdscr, 1); // nodelay选项使getch成为非阻塞调用。如果没有输入就绪,getch将返回ERR。
	(void)keypad(stdscr, 1); //允许使用功能键,例如:F1、F2、方向键等功能键。
	(void)curs_set(0);// curs_set例程将光标状态设置为不可见、正常或非常可见,可见性分别为0、1或2。
}

Linux下C/C++实现cpustat

...
static int get_pid_max_digits(void)
{
	ssize_t n;
	int digits, fd;
	const int default_digits = 6;
	const int min_digits = 5;
	char buf[32];

	digits = default_digits;
	fd = open("/proc/sys/kernel/pid_max", O_RDONLY);
	if (fd < 0)
		goto ret;
	n = read(fd, buf, sizeof(buf) - 1);
	(void)close(fd);
	if (n < 0)
		goto ret;

	buf[n] = '\0';
	digits = 0;
	while (buf[digits] >= '0' && buf[digits] <= '9')
		digits++;
	if (digits < min_digits)
		digits = min_digits;
ret:
	return digits;
}


static void info_banner_dump(const double time_now,int umax_w,int smax_w,int usmax_w)
{
	static char str[256];
	char *ptr = str;
	int i;
	char tmp[256];
	size_t n, sz = sizeof(str);

	snprintf(tmp, sizeof(tmp), "%*s %*s %*s ",
		usmax_w, "%CPU",
		umax_w, "%USR",
		smax_w, "%SYS");
	n = strlen(tmp);

	(void)strncpy(ptr, tmp, sizeof(str));
	ptr += n;
	sz -= n;
	for (i = 0; i < pid_max_digits - 3; i++, ptr++)
		*ptr = ' ';
	sz -= i;
	(void)strncpy(ptr, "PID S  CPU    Time Task", sz);
	ptr += 23;

	if (UNLIKELY(opt_flags & OPT_TIMESTAMP)) {
		struct tm tm;

		get_tm(time_now, &tm);
		(void)strncpy(ptr, "  (", 4);
		ptr += 3;
		ptr += putint(ptr, 2, tm.tm_hour, true);
		*ptr = ':';
		ptr++;
		ptr += putint(ptr, 2, tm.tm_min, true);
		*ptr = ':';
		ptr++;
		ptr += putint(ptr, 2, tm.tm_sec, true);
		*ptr = ')';
		ptr++;
	}
	*ptr = '\0';
	df.df_putstrnl(str, ptr - str);
}

...

static inline void info_total_dump(const double u_total,const double s_total)
{
	if (UNLIKELY(opt_flags & OPT_TOTAL)) {
		char buffer[256], *ptr = buffer;

		ptr += putdouble(ptr, u_total + s_total, 100, 6);
		*(ptr++) = ' ';
		ptr += putdouble(ptr, u_total, 100, 6);
		*(ptr++) = ' ';
		ptr += putdouble(ptr, s_total, 100, 6);
		*(ptr++) = ' ';
		ptr += putstr(ptr, 5, "Total");
		df.df_putstrnl(buffer, ptr - buffer);
	}
}

static char *load_average(void)
{
	static char buffer[4096];
	char *ptr = buffer;
	ssize_t len;
	int fd, skip = 3;

	if (UNLIKELY((fd = open("/proc/loadavg", O_RDONLY)) < 0))
		goto unknown;
	len = read(fd, buffer, sizeof(buffer) - 1);
	(void)close(fd);
	if (UNLIKELY(len < 1))
		goto unknown;
	buffer[len] = '\0';

	for (;;) 
	{
		if (*ptr == '\0') 
		{
			skip--;
			break;
		}
		if (*ptr == ' ') 
		{
			skip--;
			if (skip == 0) 
			{
				*ptr = '\0';
				break;
			}
		}
		ptr++;
	}
	if (skip != 0)
		goto unknown;

	return buffer;
unknown:
	return "unknown";

}

...


int main(int argc, char **argv)
{
...

	for (;;) {
		int c = getopt(argc, argv, "acdDghiln:qr:sSt:Tp:xX");
		if (c == -1)
			break;
		switch (c) 
		{
		case 'a':
			opt_flags |= OPT_TICKS_ALL;
			break;
		case 'c':
			opt_flags |= OPT_CMD_COMM;
			break;
		case 'd':
			opt_flags |= OPT_DIRNAME_STRIP;
			break;
		case 'D':
			opt_flags |= (OPT_SAMPLES | OPT_DISTRIBUTION);
			break;
		case 'g':
			opt_flags |= OPT_GRAND_TOTAL;
			break;
		case 'h':
			show_usage();
			exit(EXIT_SUCCESS);
		case 'i':
			opt_flags |= OPT_IGNORE_SELF;
			break;
		case 'l':
			opt_flags |= OPT_CMD_LONG;
			break;
		case 'n':
			errno = 0;
			n_lines = (int32_t)strtol(optarg, NULL, 10);
			if (errno) 
			{
				(void)fprintf(stderr, "Invalid value for -n option\n");
				exit(EXIT_FAILURE);
			}
			if (n_lines < 1) 
			{
				(void)fprintf(stderr,
					"-n option must be greater than 0\n");
				exit(EXIT_FAILURE);
			}
			break;
		case 'p':
			errno = 0;
			opt_pid = strtol(optarg, NULL, 10);
			if (errno) 
			{
				(void)fprintf(stderr,
					"Invalid value for -o option\n");
				exit(EXIT_FAILURE);
			}
			opt_flags |= OPT_MATCH_PID;
			break;
		case 's':
			opt_flags |= OPT_CMD_SHORT;
			break;
		case 'S':
			opt_flags |= OPT_TIMESTAMP;
			break;
		case 't':
			opt_threshold = atof(optarg);
			if (opt_threshold < 0.0) {
				(void)fprintf(stderr,
					"-t threshold must be 0 or more.\n");
				exit(EXIT_FAILURE);
			}
			break;
		case 'T':
			opt_flags |= OPT_TOTAL;
			break;
		case 'q':
			opt_flags |= OPT_QUIET;
			break;
		case 'r':
			csv_results = optarg;
			opt_flags |= OPT_SAMPLES;
			break;
		case 'x':
			opt_flags |= OPT_EXTRA_STATS;
			break;
		case 'X':
			opt_flags |= OPT_TOP;
			break;
		default:
			show_usage();
			exit(EXIT_FAILURE);
		}
	}
	...
}

运行结果:

当不带任何参数运行时,cpustat 默认会显示以下信息:

cpustat

每秒转储CPU统计数据,直到停止。

cpustat -n 20 60

每60秒转储前20个CPU消耗任务,直到停止。

cpustat 10 5

每10秒转储一次CPU统计数据,仅5次。

cpustat -x -D -a 1 300

每隔5分钟收集一次统计数据,并显示额外的CPU统计数据运行结束时每个任务和每个CPU的利用率分布。此外,比例CPU利用率除以CPU数量,因此100%利用率意味着100%CPU而不是1个CPU的100%。

cpustat -s 100 -s 10 -n 20


这将每100毫秒对所有进程进行一次采样,并在10次采样后(即每5秒)汇总此数据。

cpustat 5 5 -gxDST

If you need the complete source code of cpustat, please add WeChat number (c17865354792)​

总结

cpustat 是 Linux 下一个用于linux下的CPU使用率监控工具。

Welcome to follow WeChat official account【程序猿编码

参考:man 5 proc

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/149319.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据概论

大数据概论大数据概论概念特点(4V)Volume(大量)Velocity(高速)Variety(多样)Value(低价值密度)应用场景发展前景部门间业务流程分析部门组织结构大数据概论 概念 大数据(BigData)&#xff0c;指无法在一定时间范围内\textcolor{Red}{无法在一定时间范围内}无法在一定时间范围…

iOS—Effective Objective—C2.0(2)

文章目录对象&#xff0c;消息&#xff0c;运行期理解“属性”概念合成与存取dynamic关键字属性特性原子性读/写权限内存管理语义方法名为什么几乎所有的属性都可以使用nonatomic&#xff1a;要点在对象的内部尽量直接访问实例变量惰性初始化&#xff1a;要点理解“对象同等性”…

2022年度总结——平凡之路

文章目录一、缘起二、回首2022三、展望2023四、结束语我是平凡的人&#xff0c;总要接受普通平凡的自己。一、缘起 我注册CSDN的时间是2021-07-25&#xff0c;这是一个值得纪念的时间。不过那时候的我并没有写博客&#xff0c;只是在CSDN游览一些文章&#xff0c;查看资料&…

一文读懂Java垃圾回收机制及算法原理万字详解

Java垃圾回收机制及算法 文章目录Java垃圾回收机制及算法垃圾回收概述垃圾回收-对象是否已死判断对象是否存活 - 引用计数算法判断对象是否存活-可达性分析算法可达性分析算法JVM之判断对象是否存活再谈引用垃圾收集算法分代收集理论标记-清除算法什么是标记-清除算法?标记-复…

读书:《卡片笔记写作法》

2023年罗胖跨年演讲时提到了一个故事&#xff0c;说Flomo的创始人有3个原则&#xff1a;一不在软件内弹广告&#xff0c;二不做永久会员&#xff0c;三不融资。我就马上试用了一下这款Flomo软件&#xff0c;然后就发现了《卡片笔记写作法》这本书。 这本书的卡片写作法来自于一…

【Qt】QtCreator新建Application项目的6类应用程序的示例

【Qt】QtCreator新建Application项目的6类应用程序的示例1、背景2、Application分类1、背景 操作系统&#xff1a;windows10专业版。 Qt版本&#xff1a;qt-opensource-windows-x86-msvc2013_64-5.7.1.exe 注意&#xff1a;安装了该exe可执行文件&#xff0c;就自动安装了qtcr…

(考研湖科大教书匠计算机网络)第一章概述-第一节:因特网概述

文章目录一&#xff1a;网络、互联网和因特网基本概念二&#xff1a;因特网发展的三个阶段三&#xff1a;ISP和基于ISP的三层结构的因特网&#xff08;1&#xff09;ISP&#xff08;2&#xff09;基于ISP的三层结构的因特网四&#xff1a;因特网的标准化工作五&#xff1a;因特…

KMP算法--子串查找问题

目录 一.前言 二.KMP算法简介 三.关键概念1&#xff1a;字符串的前后缀 四. 关键概念2&#xff1a;字符串相等前后缀与最长相等前后缀长度 五.关键概念3&#xff1a;Next数组 六.Next数组在算法中的应用&#xff1a; 七.模式串Next数组的构建 先膜拜一下三位神仙&#x…

面试前端数组去重,我会问这3个小问题

关于数组去重&#xff0c;已经是一个老生常谈的问题了&#xff0c;网络上已经有N篇关于数组去重的讲解了&#xff0c;所以&#xff0c;凡是能看见这篇博客的&#xff0c;我们都是有缘人&#xff0c;希望2023年你可以乘风破浪&#xff0c;职击沧海。而一般面试的时候&#xff0c…

MySQL调优-高性能业务表结构设计

目录 前言记录&#xff1a; 数据库表设计 范式设计 什么是范式&#xff1f; 数据库设计的第一范式 数据库设计的第二范式 数据库设计的第三范式 范式说明 反范式设计 什么叫反范式化设计&#xff1f; 反范式设计-商品信息 范式化和反范式总结 实际工作中的反范式实…

C++ stack和queue

1. stack的介绍和使用1.1 stack的介绍1. stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入与提取操作。2. stack是作为容器适配器被实现的&#xff0c;容器适配器即是对特定类封装作为其底层的容器&…

基于深度学习的自然语言处理

1、什么是自然语言处理&#xff1f; 自然语言处理&#xff08;Natural Language Processing, NLP&#xff09;是计算机科学领域与人工智能领域中的一个重要方向。它研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。自然语言处理是一门融语言学、计算机科学、…

【信号与系统】预习笔记(每日更新ing)

2023.1.8已打卡 信号与系统&#xff08;一&#xff09;信号与系统概述1.0 常见三角公式1.1 信号与系统1.2 信号的表述、分类1.3 信号的运算&#xff08;二&#xff09;连续系统的时域分析&#xff08;三&#xff09;离散系统的时域分析&#xff08;四&#xff09;傅里叶变换与频…

软件质量保证与软件测试复习文档

目录 引言&#xff1a; 内容&#xff1a; 一、Ron patton《软件测试》中谈到的软件缺陷的定义被业界广泛认可&#xff0c;主要包括哪五条&#xff1f; 二、软件测试人员的主要工作职责是什么&#xff0c;一般围绕哪几个重要文档开展工作&#xff1f; 三、什么是软件测试模…

差分算法介绍

一、基本概念 差分算法是前缀和算法的逆运算&#xff0c;可以快速的对数组的某一区间进行计算操作。 例如&#xff0c;有一数列 a[1],a[2],.…a[n]&#xff0c;且令 b[i] a[i]-a[i-1],b[1]a[1]&#xff0c;那么就有 a[i] b[1]b[2].…b[i] a[1]a[2]-a[1]a[3]-a[2].…a[i]-a[i…

电脑开机密码忘记了怎么办?

相信很多朋友为了保护自己的隐私&#xff0c;都会在自己的电脑设置开机密码&#xff0c;但有时候电脑太久没用&#xff0c;就有可能忘记开机密码了&#xff0c;这可怎么办&#xff1f;别着急&#xff0c;今天就跟大家分享两种苹果电脑忘记开机密码解决方式&#xff0c;适用于Ma…

使用Junit进行单元测试的简单例子

首先新建一个工程&#xff0c;选择合适的路径和JDK版本&#xff0c;其它默认就行。 把Main.java内容改为如下。 后面就是对add方法增加单元测试 public class Main {public static void main(String[] args) {System.out.println("Hello world!");}public static i…

计算机网络——应用层协议原理

目录 1. 网络应用体系结构 1.1 客户机/服务器结构 1.2 P2P结构 1.3 混合结构 2. 进程通信 2.1 标识进程通信 2.2 套接字(socket) 3. 网络应用的服务需求 3.1 可靠数据传输 3.2 吞吐量 3.3 定时 3.4 安全性 3.5 常见网络应用的要求 4. 因特网提供的传输服务…

ArcGIS基础实验操作100例--实验69布局中添加报表和Excel图表

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验69 布局中添加报表和Excel图表 目录 一、实验背景 二、实验数据 三、实验步骤 &…

最快的表格:Dapfor Wpf GridControl

Dapfor Wpf GridControl 特性Wpf GridControl 是我们网格的第三个版本&#xff0c;它基于 WPF 技术。前两个产品是基于Microsoft WinForms 技术的MFC Grid 和.Net Grid。在网格的第三次迭代中&#xff0c;Dapfor 的专家采用了以前产品的最佳功能&#xff0c;从而产生了比其他供…