web123456

Linux programming: Use C++ to monitor CPU usage of processes and threads

#include <> #include <vector> #include <unordered_set> #include <memory> #include <iostream> #include <fstream> #include <sstream> #include <cstring> #include <limits> #include <> // Class used to monitor process and thread CPU load class ProcessCpuLoad { public: // Data structure used to store results struct Result { int id; // Process ID or thread ID float load; // CPU load std::string name; // Process name or thread name }; // Run monitoring once based on the process or thread name or PID list 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) { // Monitor the process and its threads MonitorProcessAndThreads(pid, std::string(comm)); } } } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } } } } // Get monitoring results std::vector<Result> GetResult() const { return results_; } private: // Monitor the CPU load of the process and all its threads 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_; //Storing monitoring results };