163 lines
5.7 KiB
C++
163 lines
5.7 KiB
C++
|
|
#include <iostream>
|
||
|
|
#include <fstream>
|
||
|
|
#include <sstream>
|
||
|
|
#include <string>
|
||
|
|
#include <vector>
|
||
|
|
#include <thread>
|
||
|
|
#include <chrono>
|
||
|
|
#include <iomanip>
|
||
|
|
#include <numeric>
|
||
|
|
#include <algorithm>
|
||
|
|
|
||
|
|
// ==========================================
|
||
|
|
// CPU 监控类 (保持不变)
|
||
|
|
// ==========================================
|
||
|
|
class CpuMonitor {
|
||
|
|
public:
|
||
|
|
CpuMonitor() { get_usage(); }
|
||
|
|
|
||
|
|
float get_usage() {
|
||
|
|
std::ifstream file("/proc/stat");
|
||
|
|
std::string line;
|
||
|
|
if (!std::getline(file, line)) return 0.0f;
|
||
|
|
|
||
|
|
std::istringstream ss(line.substr(3));
|
||
|
|
unsigned long long user, nice, system, idle, iowait, irq, softirq, steal;
|
||
|
|
ss >> user >> nice >> system >> idle >> iowait >> irq >> softirq >> steal;
|
||
|
|
|
||
|
|
unsigned long long current_idle = idle + iowait;
|
||
|
|
unsigned long long current_non_idle = user + nice + system + irq + softirq + steal;
|
||
|
|
unsigned long long current_total = current_idle + current_non_idle;
|
||
|
|
|
||
|
|
unsigned long long total_diff = current_total - prev_total;
|
||
|
|
unsigned long long idle_diff = current_idle - prev_idle;
|
||
|
|
|
||
|
|
prev_idle = current_idle;
|
||
|
|
prev_total = current_total;
|
||
|
|
|
||
|
|
if (total_diff == 0) return 0.0f;
|
||
|
|
return (float)(total_diff - idle_diff) * 100.0f / total_diff;
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
unsigned long long prev_idle = 0;
|
||
|
|
unsigned long long prev_total = 0;
|
||
|
|
};
|
||
|
|
|
||
|
|
// ==========================================
|
||
|
|
// NPU 读取函数 (修改为读取所有核心)
|
||
|
|
// ==========================================
|
||
|
|
std::string get_npu_usage_str() {
|
||
|
|
std::ifstream file("/sys/kernel/debug/rknpu/load");
|
||
|
|
if (!file.is_open()) return "N/A (No Perm)";
|
||
|
|
|
||
|
|
std::string line;
|
||
|
|
if (std::getline(file, line)) {
|
||
|
|
// RK3588 通常格式: "NPU load: Core0: 0%, Core1: 0%, Core2: 0%,"
|
||
|
|
// 我们去掉前面的 "NPU load:" 前缀,只保留 Core 信息
|
||
|
|
size_t pos = line.find("NPU load:");
|
||
|
|
if (pos != std::string::npos) {
|
||
|
|
line = line.substr(pos + 9);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 简单的字符串清理:去掉多余空格,去掉结尾逗号
|
||
|
|
std::string clean_line;
|
||
|
|
bool last_space = false;
|
||
|
|
for (char c : line) {
|
||
|
|
if (c == ',') continue; // 去掉逗号
|
||
|
|
if (isspace(c)) {
|
||
|
|
if (!last_space) {
|
||
|
|
clean_line += ' ';
|
||
|
|
last_space = true;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
clean_line += c;
|
||
|
|
last_space = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return clean_line;
|
||
|
|
}
|
||
|
|
return "Idle";
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==========================================
|
||
|
|
// RGA 读取函数 (根据你找到的路径修改)
|
||
|
|
// ==========================================
|
||
|
|
std::string get_rga_usage_str() {
|
||
|
|
std::ifstream file("/sys/kernel/debug/rkrga/load");
|
||
|
|
if (!file.is_open()) return "N/A";
|
||
|
|
|
||
|
|
std::string line;
|
||
|
|
std::stringstream ss;
|
||
|
|
bool found_any = false;
|
||
|
|
int core_idx = 0;
|
||
|
|
|
||
|
|
while (std::getline(file, line)) {
|
||
|
|
// 忽略第一行 "num of scheduler"
|
||
|
|
if (line.find("scheduler") != std::string::npos && line.find("=") != std::string::npos && line.find("%") == std::string::npos) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 寻找包含 "%" 的行,通常负载都在这些行里
|
||
|
|
if (line.find("%") != std::string::npos) {
|
||
|
|
// 尝试提取这一行里的最后一个数字
|
||
|
|
// 假设格式类似: "scheduler[0]: full_load = 0.0%, load = 12.5%"
|
||
|
|
// 或者简单点: "load = 12%"
|
||
|
|
|
||
|
|
// 简单粗暴法:找到 "%" 前面的数字
|
||
|
|
size_t percent_pos = line.rfind('%'); // 找最后一个 %
|
||
|
|
if (percent_pos != std::string::npos && percent_pos > 0) {
|
||
|
|
// 向前回溯找到数字起始位置
|
||
|
|
size_t num_end = percent_pos;
|
||
|
|
size_t num_start = num_end;
|
||
|
|
while (num_start > 0 && (isdigit(line[num_start-1]) || line[num_start-1] == '.')) {
|
||
|
|
num_start--;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (num_start < num_end) {
|
||
|
|
std::string num_str = line.substr(num_start, num_end - num_start);
|
||
|
|
try {
|
||
|
|
float load = std::stof(num_str);
|
||
|
|
ss << "C" << core_idx++ << ":" << std::fixed << std::setprecision(0) << load << "% ";
|
||
|
|
found_any = true;
|
||
|
|
} catch (...) {}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!found_any) return "Idle (fmt err)";
|
||
|
|
return ss.str();
|
||
|
|
}
|
||
|
|
// ==========================================
|
||
|
|
// 主函数
|
||
|
|
// ==========================================
|
||
|
|
int main() {
|
||
|
|
CpuMonitor cpu_mon;
|
||
|
|
|
||
|
|
std::cout << "=== RK3588 System Monitor ===" << std::endl;
|
||
|
|
// 打印更宽的表头
|
||
|
|
std::cout << "----------------------------------------------------------------------------------" << std::endl;
|
||
|
|
std::cout << "| CPU | NPU (3 Cores) | RGA (Cores) |" << std::endl;
|
||
|
|
std::cout << "----------------------------------------------------------------------------------" << std::endl;
|
||
|
|
|
||
|
|
while (true) {
|
||
|
|
float cpu = cpu_mon.get_usage();
|
||
|
|
std::string npu = get_npu_usage_str();
|
||
|
|
std::string rga = get_rga_usage_str();
|
||
|
|
|
||
|
|
// 格式化输出
|
||
|
|
// CPU: 占用 6 格
|
||
|
|
// NPU: 占用 38 格 (预留给 Core0: xx% Core1: xx% Core2: xx%)
|
||
|
|
// RGA: 占用 28 格
|
||
|
|
std::cout << "\r| "
|
||
|
|
<< std::fixed << std::setprecision(1) << std::setw(5) << cpu << "% | "
|
||
|
|
<< std::left << std::setw(38) << npu << " | "
|
||
|
|
<< std::setw(28) << rga << " |"
|
||
|
|
<< std::flush;
|
||
|
|
|
||
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|