【Rust调用Windows API】读取系统CPU利用率

前言

本片文章介绍使用Rust调用Windows系统API读取当前CPU的利用率(Kernel、User)、空闲率。

依赖

需要使用processthreadsapi.h头文件中定义的函数,在Cargo.toml加上这个feature

shell 复制代码
winapi = { version = "0.3.9", features = ["processthreadsapi"] }

实现

接口函数定义

读取CPU利用率需要读取两次CPU的利用时间来计算,使用 GetSystemTimes 函数:

rust 复制代码
pub fn GetSystemTimes(
    lpIdleTime: LPFILETIME,
    lpKernelTime: LPFILETIME,
    lpUserTime: LPFILETIME,
) -> BOOL;

函数接收三个参数,返回读取结果

  • lpIdleTime :指向 FILETIME 的指针,此结构接收系统处于空闲状态的时间量
  • lpKernelTime :指向FILETIME 的指针,此结构接收系统处于内核模式的时间量,其中包含空闲状态
  • lpUserTime :指向FILETIME 的指针,此结构接收系统处于用户模式的时间量

读取时间量

首先用Rust实现读取这三个时间量的函数(Result和WinError是自定义的,详情见上一篇文章:系统错误代码转为可读文本信息):

rust 复制代码
use winapi::shared::minwindef::FILETIME;
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::processthreadsapi::GetSystemTimes;

pub struct SystemTimes {
    idle: FILETIME,
    kernel: FILETIME,
    user: FILETIME,
}
///
 获取自开机以来CPU时间信息,可用于计算CPU Usage
pub fn get_system_times() -> error::Result<SystemTimes> {
    let mut idle: FILETIME = unsafe { std::mem::zeroed() };
    let mut kernel: FILETIME = unsafe { std::mem::zeroed() };
    let mut user: FILETIME = unsafe { std::mem::zeroed() };
    unsafe {
        //  https://learn.microsoft.com/zh-cn/windows/win32/api/processthreadsapi/nf-processthreadsapi-getsystemtimes
        let res = GetSystemTimes(
            &mut idle as *mut FILETIME,
            &mut kernel as *mut FILETIME,
            &mut user as *mut FILETIME,
        );

        if res == 0 {
            return Err(WinError::with_code(GetLastError()));
        }
    };

    Ok(SystemTimes::new(idle, kernel, user))
}

解释时间量

这个函数得到的是一个封装了三个时间量的自定义结构体 SystemTimes,但里面的时间并不是我们常规使用的以毫秒或纳秒为单位的数字表示,而是以一个单位为百纳秒的高32位和低32位组成的结构体,直白的说它表示的是一个64位整数,只是这个整数分为高和低两段(为了兼容以前的32位机器),单位为百纳秒,百纳秒就是 100 纳秒。

这是FILETIME的定义

rust 复制代码
STRUCT!{#[debug] struct FILETIME {
    dwLowDateTime: DWORD,
    dwHighDateTime: DWORD,
}}

下面是我写的几个翻译FILETIME的工具函数,这几个函数是通用的,后面但凡涉及到FILETIME结构体的解析都可以使用它。

rust 复制代码
use std::time::Duration;
use winapi::shared::minwindef::FILETIME;

/// 将C中的 FILETIME 转为64位数字,单位为百纳秒
pub fn parse_filetime(filetime: FILETIME) -> u64 {
    u64::wrapping_shl(filetime.dwHighDateTime as u64, 32) | filetime.dwLowDateTime as u64
}

/// 解析 FILETIME 为 Duration,精度为纳秒
pub fn parse_filetime_duration(filetime: FILETIME) -> Duration {
    Duration::from_nanos(parse_filetime(filetime) * 100)
}

/// 计算两个 FILETIME 时间间隔,单位百纳秒
pub fn calculate_time_gap(start: FILETIME, end: FILETIME) -> i64 {
    let a = parse_filetime(start);
    let b = parse_filetime(end);

    (b - a) as i64
}

这里提示一下:左位移在Rust里面可能存在溢出,不能像其他语言这样写:

java 复制代码
a << 32 | b

Rust有溢出检查,有存在溢出的可能都通过不了编译,所以这里先转为64位再左位移,位移使用 wrapping_shl 函数

计算CPU利用率

计算CPU利用率需要两次间隔一定时间来算,这里写一个测试代码,每隔1秒读取一次CPU使用时间量,循环10次,计算出每秒CPU的使用情况

rust 复制代码
#[test]
pub fn test_system_times() {
    let mut count = 0;
    let mut last_times = get_system_times().unwrap();
    while count < 10 {
        sleep(Duration::from_secs(1));

        let cur_times = get_system_times().unwrap();

        let idle = calculate_time_gap(last_times.get_idle(), cur_times.get_idle()) as f64;
        let kernel = calculate_time_gap(last_times.get_kernel(), cur_times.get_kernel()) as f64;
        let user = calculate_time_gap(last_times.get_user(), cur_times.get_user()) as f64;

        let sum = kernel + user;

        let idle_percent = idle * 100.0 / sum;
        let cpu_percent = (sum - idle) * 100.0 / sum;

        let kernel_percent = (kernel - idle) * 100.0 / sum;
        let user_percent = user * 100.0 / sum;

        println!("CPU利用率:{:.2}% (Kernel: {:.2}%\tUser:{:.2}%)\tCPU空闲率:{:.2}%", cpu_percent, kernel_percent, user_percent, idle_percent);

        last_times = cur_times;
        count += 1;
    }
}

运行结果

text 复制代码
CPU利用率:12.60% (Kernel: 6.04%	User:6.56%)	CPU空闲率:87.40%
CPU利用率:2.33% (Kernel: 0.78%	User:1.55%)	CPU空闲率:97.67%
CPU利用率:1.56% (Kernel: 0.78%	User:0.78%)	CPU空闲率:98.44%
CPU利用率:7.03% (Kernel: 3.39%	User:3.65%)	CPU空闲率:92.97%
CPU利用率:0.78% (Kernel: 0.52%	User:0.26%)	CPU空闲率:99.22%
CPU利用率:1.56% (Kernel: 0.00%	User:1.56%)	CPU空闲率:98.44%
CPU利用率:2.05% (Kernel: 0.77%	User:1.28%)	CPU空闲率:97.95%
CPU利用率:4.74% (Kernel: 2.63%	User:2.11%)	CPU空闲率:95.26%
CPU利用率:0.52% (Kernel: 0.26%	User:0.26%)	CPU空闲率:99.48%
CPU利用率:2.33% (Kernel: 1.04%	User:1.30%)	CPU空闲率:97.67%
相关推荐
AI袋鼠帝8 小时前
Claude4.5+Gemini3 接管电脑桌面,这回是真无敌了..
人工智能·windows·aigc
獨枭9 小时前
Windows 下安装与使用 Miniconda 完整指南
windows
命里有定数11 小时前
保姆级教程:在 Windows (WSL2) 下本地部署 Qwen3-ASR
windows
暴躁小师兄数据学院11 小时前
【WEB3.0零基础转行笔记】Rust编程篇-第一讲:课程简介
rust·web3·区块链·智能合约
lucky670714 小时前
Windows 上彻底卸载 Node.js
windows·node.js
编程小白202614 小时前
从 C++ 基础到效率翻倍:Qt 开发环境搭建与Windows 神级快捷键指南
开发语言·c++·windows·qt·学习
凯子坚持 c16 小时前
CANN 性能剖析实战:从原始事件到交互式火焰图
windows·microsoft
开开心心就好17 小时前
发票合并打印工具,多页布局设置实时预览
linux·运维·服务器·windows·pdf·harmonyos·1024程序员节
獨枭17 小时前
PyCharm 跑通 SAM 全流程实战
windows
仙剑魔尊重楼17 小时前
音乐制作电子软件FL Studio2025.2.4.5242中文版新功能介绍
windows·音频·录屏·音乐·fl studio