Qt实现跨平台获取CPU和内存使用率(Windows/Linux)

在Qt项目开发中,经常需要监控系统的CPU和内存使用率,而不同操作系统(Windows/Linux)的实现方式差异较大。本文将分享一个跨平台的getSystemUsage函数,分别适配Windows和Linux系统,同时提供完整的可运行示例。

一、核心函数:getSystemUsage

该函数的核心思路是:通过Qt的QProcess调用系统原生命令,解析命令输出结果,最终得到CPU和内存使用率。

1. 函数实现完整代码

#include <QCoreApplication>
#include <QProcess>
#include <QDebug>
#include <QStringList>
#include <QRegExp>

// 获取CPU和内存使用率(跨平台:Windows/Linux)
void getSystemUsage()
{
#ifdef Q_OS_WIN
    // ========== Windows平台实现 ==========
    // 1. 获取CPU使用率:使用typeperf(比wmic更精准,实时性更好)
    QProcess process;
    // typeperf命令参数:查询总CPU使用率,只输出1次结果
    process.start("typeperf", QStringList() << "\\Processor(_Total)\\% Processor Time" << "-sc" << "1");
    process.waitForFinished(5000); // 超时5秒,避免进程卡死
    QString cpuOutput = process.readAllStandardOutput();

    // 解析typeperf输出:第三行是 "时间戳","CPU使用率值" 格式
    QStringList cpuLines = cpuOutput.split("\n", QString::SkipEmptyParts);
    if (cpuLines.size() >= 3) {
        QString dataLine = cpuLines[2].trimmed();
        QStringList parts = dataLine.split(",");
        if (parts.size() >= 2) {
            QString cpuUsageStr = parts[1].trimmed().replace("\"", "");
            double cpuUsage = cpuUsageStr.toDouble();
            qDebug() << "CPU Usage:" << cpuUsage << "%";
        }
    }

    // 2. 获取内存使用率:使用wmic命令(Windows原生,数据准确)
    process.start("wmic OS get FreePhysicalMemory,TotalVisibleMemorySize /Value");
    process.waitForFinished(5000);
    QString memOutput = process.readAllStandardOutput();

    QStringList memLines = memOutput.split("\n", QString::SkipEmptyParts);
    qint64 freeMemory = 0;
    qint64 totalMemory = 0;
    for (const QString& line : memLines) {
        if (line.startsWith("FreePhysicalMemory")) {
            freeMemory = line.split("=").last().trimmed().toLongLong();
        } else if (line.startsWith("TotalVisibleMemorySize")) {
            totalMemory = line.split("=").last().trimmed().toLongLong();
        }
    }
    if (totalMemory > 0) {
        double memUsage = (totalMemory - freeMemory) * 100.0 / totalMemory;
        qDebug() << "Memory Usage:" << memUsage << "%";
    }
#else
    // ========== Linux平台实现 ==========
    // 1. 获取CPU使用率:使用top命令(-bn1表示非交互模式,只输出1次)
    QProcess process;
    process.start("top -bn1 | grep 'Cpu(s)'");
    process.waitForFinished(5000);
    QString cpuOutput = process.readAllStandardOutput();

    // 解析top输出的CPU信息
    QStringList cpuParts = cpuOutput.split(",");
    if (cpuParts.size() > 0) {
        QString cpuUsagePart = cpuParts[0].split(":").last().trimmed();
        qDebug() << "CPU Usage:" << cpuUsagePart;
    }

    // 2. 获取内存使用率:使用free命令(-m表示以MB为单位)
    process.start("free -m");
    process.waitForFinished(5000);
    QString memOutput = process.readAllStandardOutput();

    QStringList memLines = memOutput.split("\n", QString::SkipEmptyParts);
    qint64 freeMemory = 0;
    qint64 totalMemory = 0;
    for (const QString& line : memLines) {
        if (line.startsWith("Mem:")) {
            QStringList memParts = line.split(QRegExp("\\s+"), QString::SkipEmptyParts);
            if (memParts.size() >= 3) {
                totalMemory = memParts[1].toLongLong(); // 总内存(MB)
                freeMemory = memParts[3].toLongLong();  // 可用内存(MB)
            }
            break;
        }
    }
    if (totalMemory > 0) {
        double memUsage = (totalMemory - freeMemory) * 100.0 / totalMemory;
        qDebug() << "Memory Usage:" << memUsage << "%";
    }
#endif
}

2. 关键逻辑解析

(1)Windows平台
  • CPU使用率:放弃传统的wmic,改用typeperf命令,原因是typeperf能获取实时CPU使用率,精度更高;

    • 命令参数说明:\\Processor(_Total)\\% Processor Time 表示查询总CPU使用率,-sc 1 表示只输出1次结果;
    • 解析逻辑:typeperf输出的第三行是有效数据行,格式为"时间戳","使用率值",拆分后提取数值即可。
  • 内存使用率:使用wmic OS get FreePhysicalMemory,TotalVisibleMemorySize /Value命令获取总物理内存和空闲物理内存;

    • 计算公式:内存使用率 = (总内存 - 空闲内存) / 总内存 * 100%
(2)Linux平台
  • CPU使用率:通过top -bn1 | grep 'Cpu(s)'命令获取CPU占用信息,-bn1表示非交互模式执行1次,避免阻塞;
  • 内存使用率:通过free -m命令(以MB为单位)获取内存信息,解析Mem:行的总内存和可用内存,计算使用率。

二、完整演示示例

下面提供包含getSystemUsage调用的完整Qt程序,可直接编译运行:

#include <QCoreApplication>
#include <QProcess>
#include <QDebug>
#include <QStringList>
#include <QRegExp>
#include <QTimer>

// 获取CPU和内存使用率(跨平台:Windows/Linux)
void getSystemUsage()
{
#ifdef Q_OS_WIN
    // Windows平台 - CPU使用率
    QProcess process;
    process.start("typeperf", QStringList() << "\\Processor(_Total)\\% Processor Time" << "-sc" << "1");
    process.waitForFinished(5000);
    QString cpuOutput = process.readAllStandardOutput();

    QStringList cpuLines = cpuOutput.split("\n", QString::SkipEmptyParts);
    if (cpuLines.size() >= 3) {
        QString dataLine = cpuLines[2].trimmed();
        QStringList parts = dataLine.split(",");
        if (parts.size() >= 2) {
            QString cpuUsage = parts[1].trimmed().replace("\"", "");
            qDebug() << "CPU Usage:" << cpuUsage.toDouble() << "%";
        }
    }

    // Windows平台 - 内存使用率
    process.start("wmic OS get FreePhysicalMemory,TotalVisibleMemorySize /Value");
    process.waitForFinished(5000);
    QString memOutput = process.readAllStandardOutput();

    QStringList memLines = memOutput.split("\n", QString::SkipEmptyParts);
    qint64 freeMemory = 0;
    qint64 totalMemory = 0;
    for (const QString& line : memLines) {
        if (line.startsWith("FreePhysicalMemory")) {
            freeMemory = line.split("=").last().trimmed().toLongLong();
        } else if (line.startsWith("TotalVisibleMemorySize")) {
            totalMemory = line.split("=").last().trimmed().toLongLong();
        }
    }
    if (totalMemory > 0) {
        qDebug() << "Memory Usage:" << (totalMemory - freeMemory) * 100.0 / totalMemory << "%";
    }
#else
    // Linux平台 - CPU使用率
    QProcess process;
    process.start("top -bn1 | grep 'Cpu(s)'");
    process.waitForFinished(5000);
    QString cpuOutput = process.readAllStandardOutput();
    QStringList cpuParts = cpuOutput.split(",");
    if (cpuParts.size() > 0) {
        QString cpuUsagePart = cpuParts[0].split(":").last().trimmed();
        qDebug() << "CPU Usage:" << cpuUsagePart;
    }

    // Linux平台 - 内存使用率
    process.start("free -m");
    process.waitForFinished(5000);
    QString memOutput = process.readAllStandardOutput();
    QStringList memLines = memOutput.split("\n", QString::SkipEmptyParts);
    qint64 freeMemory = 0;
    qint64 totalMemory = 0;
    for (const QString& line : memLines) {
        if (line.startsWith("Mem:")) {
            QStringList memParts = line.split(QRegExp("\\s+"), QString::SkipEmptyParts);
            if (memParts.size() >= 3) {
                totalMemory = memParts[1].toLongLong();
                freeMemory = memParts[3].toLongLong();
            }
            break;
        }
    }
    if (totalMemory > 0) {
        qDebug() << "Memory Usage:" << (totalMemory - freeMemory) * 100.0 / totalMemory << "%";
    }
#endif
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 单次调用测试
    qDebug() << "===== 首次获取系统使用率 =====";
    getSystemUsage();

    // 定时器定时调用(每5秒获取一次)
    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, []() {
        qDebug() << "\n===== 定时获取系统使用率 =====";
        getSystemUsage();
    });
    timer.start(5000); // 5秒执行一次

    return a.exec();
}

三、运行效果

1. Windows平台输出

===== 首次获取系统使用率 =====
CPU Usage: 15.625 %
Memory Usage: 45.2 %

===== 定时获取系统使用率 =====
CPU Usage: 12.5 %
Memory Usage: 45.3 %

2. Linux平台输出

===== 首次获取系统使用率 =====
CPU Usage: 2.0%us
Memory Usage: 38.5 %

===== 定时获取系统使用率 =====
CPU Usage: 1.8%us
Memory Usage: 38.6 %

四、注意事项

  1. 命令依赖:确保系统中存在typeperf(Windows)、wmic(Windows)、top(Linux)、free(Linux)命令,一般系统默认自带;
  2. 超时处理process.waitForFinished(5000)设置5秒超时,避免进程卡死导致程序无响应;
  3. 容错解析:代码中增加了数组越界、数值转换的容错判断,避免因命令输出格式变化导致程序崩溃;
  4. Qt跨平台宏:使用Q_OS_WIN宏区分Windows和Linux平台,需在项目文件(.pro)中确保QT += core,并正确配置Qt编译环境;
  5. 权限问题:Linux下部分系统可能需要普通用户权限即可执行top/free,无需root。

总结

本文实现的getSystemUsage函数基于Qt的QProcess调用系统原生命令,完美适配Windows和Linux平台,能够精准获取CPU和内存使用率。代码可直接集成到Qt项目中,适用于系统监控、性能分析等场景。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐