Linux编程: 使用 C++ 监控进程和线程的 CPU 使用情况

时间:2025-04-11 07:59:44
#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_; // 存储监控结果 };