Linux编程: 使用 C++ 监控进程和线程的 CPU 使用情况
#include <>
#include <vector>
#include <unordered_set>
#include <memory>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
#include <limits>
#include <>
// 用于监控进程和线程CPU负载的类
class ProcessCpuLoad {
public:
// 用于存储结果的数据结构
struct Result {
int id; // 进程ID或线程ID
float load; // CPU负载
std::string name; // 进程名称或线程名称
};
// 根据进程或线程名称或PID列表运行一次监控
void RunOnce(const std::vector<std::string>& process_names_or_pids) {
results_.clear();
std::unordered_set<std::string> target_set(process_names_or_pids.begin(), process_names_or_pids.end());
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir("/proc"), closedir);
if (!dir) {
std::cerr << "Failed to open /proc directory." << std::endl;
return;
}
struct dirent* entry;
while ((entry = readdir(dir.get())) != nullptr) {
if (entry->d_type == DT_DIR) {
int pid = atoi(entry->d_name);
if (pid > 0) {
std::string comm_path = "/proc/" + std::string(entry->d_name) + "/comm";
try {
std::ifstream comm_file(comm_path);
if (!comm_file.is_open()) {
std::cerr << "Failed to open " << comm_path << std::endl;
continue;
}
char comm[256];
if (comm_file >> comm) {
std::string pid_str = std::to_string(pid);
bool match_found = false;
for (const auto& target : target_set) {
if (pid_str.find(target) != std::string::npos || std::string(comm).find(target) != std::string::npos) {
match_found = true;
break;
}
}
if (match_found) {
// 监控该进程及其线程
MonitorProcessAndThreads(pid, std::string(comm));
}
}
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
}
}
}
}
// 获取监控结果
std::vector<Result> GetResult() const {
return results_;
}
private:
// 监控进程及其所有线程的CPU负载
void MonitorProcessAndThreads(int pid, const std::string& process_name) {
std::string task_path = "/proc/" + std::to_string(pid) + "/task";
std::unique_ptr<DIR, decltype(&closedir)> task_dir(opendir(task_path.c_str()), closedir);
if (!task_dir) {
std::cerr << "Failed to open " << task_path << std::endl;
return;
}
struct dirent* task_entry;
while ((task_entry = readdir(task_dir.get())) != nullptr) {
if (task_entry->d_type == DT_DIR) {
int tid = atoi(task_entry->d_name);
if (tid > 0) {
std::string stat_path = task_path + "/" + std::string(task_entry->d_name) + "/stat";
try {
std::ifstream stat_file(stat_path);
if (!stat_file.is_open()) {
std::cerr << "Failed to open " << stat_path << std::endl;
continue;
}
unsigned long utime, stime;
stat_file.ignore(std::numeric_limits<std::streamsize>::max(), ')');
stat_file.ignore(std::numeric_limits<std::streamsize>::max(), ' ');
for (int i = 0; i < 13; ++i) stat_file.ignore(std::numeric_limits<std::streamsize>::max(), ' ');
stat_file >> utime >> stime;
float total_time = static_cast<float>(utime + stime) / sysconf(_SC_CLK_TCK);
results_.push_back({tid, total_time, process_name + " (Thread " + std::to_string(tid) + ")"});
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
}
}
}
}
std::vector<Result> results_; // 存储监控结果
};