From a1f51b42fdbf706c7ac03c55f4f477704181b624 Mon Sep 17 00:00:00 2001 From: Ragab Hassan Date: Sat, 7 Oct 2023 16:02:02 +0300 Subject: [PATCH] [RH] Add my implementation --- CMakeLists.txt | 4 +- include/format.h | 2 +- include/linux_parser.h | 1 + include/process.h | 37 ++++- include/processor.h | 11 +- include/system.h | 36 +++-- src/format.cpp | 16 +- src/linux_parser.cpp | 327 +++++++++++++++++++++++++++++++++++----- src/ncurses_display.cpp | 44 +++--- src/process.cpp | 116 +++++++++++--- src/processor.cpp | 29 +++- src/system.cpp | 118 ++++++++++++--- 12 files changed, 620 insertions(+), 121 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a63c8bc0..488a5ed2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,5 +11,5 @@ add_executable(monitor ${SOURCES}) set_property(TARGET monitor PROPERTY CXX_STANDARD 17) target_link_libraries(monitor ${CURSES_LIBRARIES}) -# TODO: Run -Werror in CI. -target_compile_options(monitor PRIVATE -Wall -Wextra) + +target_compile_options(monitor PRIVATE -Wall -Wextra -Werror) diff --git a/include/format.h b/include/format.h index baace910..5c8938dc 100644 --- a/include/format.h +++ b/include/format.h @@ -4,7 +4,7 @@ #include namespace Format { -std::string ElapsedTime(long times); // TODO: See src/format.cpp +std::string ElapsedTime(long times); }; // namespace Format #endif \ No newline at end of file diff --git a/include/linux_parser.h b/include/linux_parser.h index 988ac069..dfa4e653 100644 --- a/include/linux_parser.h +++ b/include/linux_parser.h @@ -52,6 +52,7 @@ std::string Ram(int pid); std::string Uid(int pid); std::string User(int pid); long int UpTime(int pid); +std::vector CpuUtilization(int pid); }; // namespace LinuxParser #endif \ No newline at end of file diff --git a/include/process.h b/include/process.h index 6b7d1c22..23b54243 100644 --- a/include/process.h +++ b/include/process.h @@ -8,16 +8,37 @@ It contains relevant attributes as shown below */ class Process { public: - int Pid(); // TODO: See src/process.cpp - std::string User(); // TODO: See src/process.cpp - std::string Command(); // TODO: See src/process.cpp - float CpuUtilization(); // TODO: See src/process.cpp - std::string Ram(); // TODO: See src/process.cpp - long int UpTime(); // TODO: See src/process.cpp - bool operator<(Process const& a) const; // TODO: See src/process.cpp + Process(int pid); + int Pid(); + std::string User(); + std::string Command(); + float CpuUtilization(); + std::string Ram(); + long int UpTime(); + bool operator<(Process const& a) const; + bool operator==(Process const& a) const; + bool KeepAlive(); + void KeepAlive(bool); + void UpdateProcess(); - // TODO: Declare any necessary private members + // DONE: Declare any necessary private members private: + int pid_; + bool keepAlive_; + std::string memUsage_; + float cpuUsage_; + float currentActiveJiffies_; + float currentTotalJiffies_; + std::string username_; + std::string command_; + bool userInitialized_; + bool commandInitialized_; + long upTime_; + + void updateUpTime(); + void updateCpuUsage(void); + void updateMemUsage(void); + }; #endif \ No newline at end of file diff --git a/include/processor.h b/include/processor.h index 6951a659..d231194e 100644 --- a/include/processor.h +++ b/include/processor.h @@ -1,12 +1,19 @@ #ifndef PROCESSOR_H #define PROCESSOR_H +#include +#include + class Processor { public: - float Utilization(); // TODO: See src/processor.cpp + float Utilization(); + Processor(); - // TODO: Declare any necessary private members + // DONE: Declare any necessary private members private: + static bool IsInitializied_; + float CurrentRunTime_; + float CurrentTotalTime_; }; #endif \ No newline at end of file diff --git a/include/system.h b/include/system.h index ae445adf..f730cb30 100644 --- a/include/system.h +++ b/include/system.h @@ -3,25 +3,39 @@ #include #include - #include "process.h" #include "processor.h" class System { public: - Processor& Cpu(); // TODO: See src/system.cpp - std::vector& Processes(); // TODO: See src/system.cpp - float MemoryUtilization(); // TODO: See src/system.cpp - long UpTime(); // TODO: See src/system.cpp - int TotalProcesses(); // TODO: See src/system.cpp - int RunningProcesses(); // TODO: See src/system.cpp - std::string Kernel(); // TODO: See src/system.cpp - std::string OperatingSystem(); // TODO: See src/system.cpp + Processor& Cpu(); + std::vector& Processes(); + float MemoryUtilization(); + long UpTime(); + int TotalProcesses(); + int RunningProcesses(); + std::string Kernel(); + std::string OperatingSystem(); - // TODO: Define any necessary private members + // DONE: Define any necessary private members private: - Processor cpu_ = {}; + Processor cpu_; std::vector processes_ = {}; + std::string systemOS_; + bool osRead_{false}; + std::string systemKernel_; + bool kernelRead_{false}; + float memoryUtilization_; + long upTime_; + int totalProcesses_; + int runningProcesses_; + + void updateMemoryUtilization(); + void updateUpTime(); + void updateTotalProcesses(); + void updateRunningProcesses(); + void updateSystemReadings(); + }; #endif \ No newline at end of file diff --git a/src/format.cpp b/src/format.cpp index 8f8f854b..47685be0 100644 --- a/src/format.cpp +++ b/src/format.cpp @@ -1,11 +1,19 @@ -#include - #include "format.h" +#include + using std::string; -// TODO: Complete this helper function +// DONE: Complete this helper function // INPUT: Long int measuring seconds // OUTPUT: HH:MM:SS // REMOVE: [[maybe_unused]] once you define the function -string Format::ElapsedTime(long seconds[[maybe_unused]]) { return string(); } \ No newline at end of file +string Format::ElapsedTime(long seconds) { + string elapsedTime; + + elapsedTime = std::to_string(seconds / (60 * 60)) + ":" + + std::to_string((seconds % (60 * 60)) / 60) + ":" + + std::to_string(seconds % 60); + + return elapsedTime; +} \ No newline at end of file diff --git a/src/linux_parser.cpp b/src/linux_parser.cpp index 51a946a1..5c1a91bd 100644 --- a/src/linux_parser.cpp +++ b/src/linux_parser.cpp @@ -1,16 +1,75 @@ +#include "linux_parser.h" + #include #include + +#include #include #include #include -#include "linux_parser.h" - using std::stof; using std::string; using std::to_string; using std::vector; +#define USER (0) +#define NICE (1) +#define SYSTEM (2) +#define IDLE (3) +#define IOWAIT (4) +#define IRQ (5) +#define SOFTIRQ (6) +#define STEAL (7) +#define GUEST (8) +#define GUEST_NICE (9) +#define NO_OF_JIFFIES (10) + +static vector Jiffies_s(10,""); + +bool searchString_helper(string regex_xpr, const string searchString, + unsigned int index, std::string& str) { + std::smatch regexMatch; + // look for regex + if (std::regex_match(searchString, regexMatch, std::regex(regex_xpr))) { + // The first sub_match is the whole string; the next + // sub_match is the first parenthesized expression. + if (regexMatch.size() > index) { + str = regexMatch[index].str(); + return true; + } + } + return false; +} + +void findSysJiffies() +{ + std::ifstream statFile(LinuxParser::kProcDirectory + LinuxParser::kStatFilename, std::ios::in); + + if (!statFile) { + return; + } + while (statFile) + { + std::string searchString; + std::getline(statFile, searchString); + std::smatch regexMatch; + // look for regex + if (std::regex_match(searchString, regexMatch, std::regex("cpu\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+).*"))) { + // The first sub_match is the whole string; the next + // sub_match is the first parenthesized expression. + if (regexMatch.size() == NO_OF_JIFFIES + 1) { + int i{0}; + for (auto &match : regexMatch) + { + if (&match == ®exMatch[0]) {continue;} + Jiffies_s[i++] = match; + } + break; + } + } + } +} // DONE: An example of how to read data from the filesystem string LinuxParser::OperatingSystem() { string line; @@ -67,50 +126,246 @@ vector LinuxParser::Pids() { return pids; } -// TODO: Read and return the system memory utilization -float LinuxParser::MemoryUtilization() { return 0.0; } +// DONE: Read and return the system memory utilization +float LinuxParser::MemoryUtilization() { + std::string totalMem; + std::string freeMem; + float memUtilization; + vector isFound(2, false); -// TODO: Read and return the system uptime -long LinuxParser::UpTime() { return 0; } + std::ifstream memInfo(kProcDirectory + kMeminfoFilename, std::ios::in); -// TODO: Read and return the number of jiffies for the system -long LinuxParser::Jiffies() { return 0; } + if (!memInfo) { + return 0.0; + } + // read Meminfo file + while (memInfo && (!isFound[0] || !isFound[1])) { + std::string lineBuffer; + std::getline(memInfo, lineBuffer); + // look for total mem + isFound[0] = isFound[0] ? isFound[0] : searchString_helper("^MemTotal:\\s*([\\d]+)\\s*.*", lineBuffer, 1, totalMem); + // look for free mem + isFound[1] = isFound[1] ? isFound[1] : searchString_helper("^MemFree:\\s*([\\d]+)\\s*.*", lineBuffer, 1, freeMem); + } + if (!isFound[0] || !isFound[1]) { + memUtilization = 0.0; + } else { + memUtilization = std::stoll(totalMem) - std::stoll(freeMem); + memUtilization /= std::stoll(totalMem); + } + return memUtilization; +} -// TODO: Read and return the number of active jiffies for a PID -// REMOVE: [[maybe_unused]] once you define the function -long LinuxParser::ActiveJiffies(int pid[[maybe_unused]]) { return 0; } +// DONE: Read and return the system uptime +long LinuxParser::UpTime() { + std::ifstream upTimeInfo(kProcDirectory + kUptimeFilename, std::ios::in); + string upTime; -// TODO: Read and return the number of active jiffies for the system -long LinuxParser::ActiveJiffies() { return 0; } + if (!upTimeInfo) { + return 0.0; + } + // read Meminfo file + while (upTimeInfo) { + std::string lineBuffer; + std::getline(upTimeInfo, lineBuffer); + if (searchString_helper("^([\\d]+)\\..*", lineBuffer, 1, upTime)) { + return (std::stol(upTime)); + } + } + return 0; +} -// TODO: Read and return the number of idle jiffies for the system -long LinuxParser::IdleJiffies() { return 0; } +// DONE: Read and return the number of jiffies for the system +long LinuxParser::Jiffies() { + return (ActiveJiffies() + IdleJiffies()); +} -// TODO: Read and return CPU utilization -vector LinuxParser::CpuUtilization() { return {}; } +// DONE: Read and return the number of active jiffies for a PID +long LinuxParser::ActiveJiffies(int pid) { + vector pidJiffies = CpuUtilization(pid); + if (pidJiffies.size() != 0) + return (std::stol(pidJiffies[0]) + std::stol(pidJiffies[1]) + std::stol(pidJiffies[2]) + std::stol(pidJiffies[3])); + else + { + return 0.0; + } + } -// TODO: Read and return the total number of processes -int LinuxParser::TotalProcesses() { return 0; } +// DONE: Read and return the number of active jiffies for the system +long LinuxParser::ActiveJiffies() { + return (std::stof(Jiffies_s[USER]) + std::stof(Jiffies_s[NICE]) + std::stof(Jiffies_s[SYSTEM]) + std::stof(Jiffies_s[IRQ]) + std::stof(Jiffies_s[SOFTIRQ]) + std::stof(Jiffies_s[GUEST]) + std::stof(Jiffies_s[GUEST_NICE])); + } -// TODO: Read and return the number of running processes -int LinuxParser::RunningProcesses() { return 0; } +// DONE: Read and return the number of idle jiffies for the system +long LinuxParser::IdleJiffies() { + return (std::stof(Jiffies_s[IDLE]) + std::stof(Jiffies_s[IOWAIT]) + std::stof(Jiffies_s[STEAL])); + } -// TODO: Read and return the command associated with a process -// REMOVE: [[maybe_unused]] once you define the function -string LinuxParser::Command(int pid[[maybe_unused]]) { return string(); } +// DONE: Read and return CPU utilization +vector LinuxParser::CpuUtilization() { + findSysJiffies(); + return Jiffies_s; +} -// TODO: Read and return the memory used by a process -// REMOVE: [[maybe_unused]] once you define the function -string LinuxParser::Ram(int pid[[maybe_unused]]) { return string(); } +// DONE: Read and return the total number of processes +int LinuxParser::TotalProcesses() { + std::ifstream totalProcessFile(kProcDirectory + kStatFilename, std::ios::in); + string totalProcess; -// TODO: Read and return the user ID associated with a process -// REMOVE: [[maybe_unused]] once you define the function -string LinuxParser::Uid(int pid[[maybe_unused]]) { return string(); } + if (!totalProcessFile) { + return 0.0; + } + // read Meminfo file + while (totalProcessFile) { + std::string lineBuffer; + std::getline(totalProcessFile, lineBuffer); + if (searchString_helper("^processes\\s*([\\d]+).*", lineBuffer, 1, totalProcess)) { + return (std::stoi(totalProcess)); + } + } + return 0; +} -// TODO: Read and return the user associated with a process -// REMOVE: [[maybe_unused]] once you define the function -string LinuxParser::User(int pid[[maybe_unused]]) { return string(); } +// DONE: Read and return the number of running processes +int LinuxParser::RunningProcesses() { + std::ifstream runningProcessFile(kProcDirectory + kStatFilename, std::ios::in); + string runningProcess; -// TODO: Read and return the uptime of a process -// REMOVE: [[maybe_unused]] once you define the function -long LinuxParser::UpTime(int pid[[maybe_unused]]) { return 0; } + if (!runningProcessFile) { + return 0.0; + } + // read Meminfo file + while (runningProcessFile) { + std::string lineBuffer; + std::getline(runningProcessFile, lineBuffer); + if (searchString_helper("^procs_running\\s*([\\d]+).*", lineBuffer, 1, runningProcess)) { + return (std::stoi(runningProcess)); + } + } + return 0; +} + +// DONE: Read and return the command associated with a process +string LinuxParser::Command(int pid [[maybe_unused]]) { + std::ifstream commandFile(kProcDirectory + to_string(pid) + kCmdlineFilename, std::ios::in); + string cmd = " "; + + if (!commandFile) { + return "0"; + } + std::getline(commandFile, cmd); + return cmd; + } + +// DONE: Read and return the memory used by a process +string LinuxParser::Ram(int pid [[maybe_unused]]) { + std::ifstream runningProcessFile(kProcDirectory + to_string(pid) + kStatusFilename, std::ios::in); + string vMem; + + if (!runningProcessFile) { + return "0"; + } + // read Meminfo file + while (runningProcessFile) { + std::string lineBuffer; + std::getline(runningProcessFile, lineBuffer); + if (searchString_helper("^VmSize:\\s+(\\d+)\\s+kB.*", lineBuffer, 1, vMem)) { + return vMem; + } + } + return string(0); + } + +// DONE: Read and return the user ID associated with a process +string LinuxParser::Uid(int pid) { + std::ifstream runningProcessFile(kProcDirectory + to_string(pid) + kStatusFilename, std::ios::in); + string pUid; + + if (!runningProcessFile) { + return ""; + } + // read Meminfo file + while (runningProcessFile) { + std::string lineBuffer; + std::getline(runningProcessFile, lineBuffer); + if (searchString_helper("^Uid:\\s+(\\d+).*", lineBuffer, 1, pUid)) { + return pUid; + } + } + return string(); +} + +// DONE: Read and return the user associated with a process +string LinuxParser::User(int pid) { + std::ifstream passwdFile(kPasswordPath, std::ios::in); + string pUid = LinuxParser::Uid(pid); + string userName; + + if (!passwdFile) { + return ""; + } + // read Meminfo file + while (passwdFile) { + std::string lineBuffer; + std::getline(passwdFile, lineBuffer); + if (searchString_helper("^([\\w-]+):.*:(?:"+ pUid +"):.*", lineBuffer, 1, userName)) { + return userName; + } + } + return string(); +} + +// DONE: Read and return the uptime of a process +long LinuxParser::UpTime(int pid) { + std::ifstream statFile(LinuxParser::kProcDirectory + std::to_string(pid) + LinuxParser::kStatFilename, std::ios::in); + long startTime; + if (!statFile) { + return{}; + } + while (statFile) + { + std::string searchString; + std::getline(statFile, searchString); + std::smatch regexMatch; + // look for regex + if (std::regex_match(searchString, regexMatch, std::regex("^(?:[\\S]+\\s+){21}(\\d+)\\s+.*"))) { + // The first sub_match is the whole string; the next + // sub_match is the first parenthesized expression. + if (regexMatch.size() > 1) { + startTime = std::stol(regexMatch[1]); + break; + } + } + + } + return startTime; + } + +std::vector LinuxParser::CpuUtilization(int pid) +{ + std::ifstream statFile(LinuxParser::kProcDirectory + std::to_string(pid) + LinuxParser::kStatFilename, std::ios::in); + vector utilization; + if (!statFile) { + return{}; + } + while (statFile) + { + std::string searchString; + std::getline(statFile, searchString); + std::smatch regexMatch; + // look for regex + if (std::regex_match(searchString, regexMatch, std::regex("^(?:[\\S]+\\s+){13}(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+).*"))) { + // The first sub_match is the whole string; the next + // sub_match is the first parenthesized expression. + if (regexMatch.size() > 1) { + for (auto &match : regexMatch) + { + if (&match == ®exMatch[0]) {continue;} + utilization.push_back(match); + } + break; + } + } + } + return utilization; +} \ No newline at end of file diff --git a/src/ncurses_display.cpp b/src/ncurses_display.cpp index c64a8ef9..0c00f1a0 100644 --- a/src/ncurses_display.cpp +++ b/src/ncurses_display.cpp @@ -1,11 +1,13 @@ +#include "ncurses_display.h" + #include + #include #include #include #include #include "format.h" -#include "ncurses_display.h" #include "system.h" using std::string; @@ -30,25 +32,25 @@ std::string NCursesDisplay::ProgressBar(float percent) { void NCursesDisplay::DisplaySystem(System& system, WINDOW* window) { int row{0}; - mvwprintw(window, ++row, 2, ("OS: " + system.OperatingSystem()).c_str()); - mvwprintw(window, ++row, 2, ("Kernel: " + system.Kernel()).c_str()); + mvwprintw(window, ++row, 2, ("OS: " + system.OperatingSystem()).c_str(), ""); + mvwprintw(window, ++row, 2, ("Kernel: " + system.Kernel()).c_str(), ""); mvwprintw(window, ++row, 2, "CPU: "); wattron(window, COLOR_PAIR(1)); - mvwprintw(window, row, 10, ""); - wprintw(window, ProgressBar(system.Cpu().Utilization()).c_str()); + mvwprintw(window, row, 10, " "); + wprintw(window, ProgressBar(system.Cpu().Utilization()).c_str(), ""); wattroff(window, COLOR_PAIR(1)); mvwprintw(window, ++row, 2, "Memory: "); wattron(window, COLOR_PAIR(1)); - mvwprintw(window, row, 10, ""); - wprintw(window, ProgressBar(system.MemoryUtilization()).c_str()); + mvwprintw(window, row, 10, " "); + wprintw(window, ProgressBar(system.MemoryUtilization()).c_str(), ""); wattroff(window, COLOR_PAIR(1)); mvwprintw(window, ++row, 2, - ("Total Processes: " + to_string(system.TotalProcesses())).c_str()); + ("Total Processes: " + to_string(system.TotalProcesses())).c_str(), ""); mvwprintw( window, ++row, 2, - ("Running Processes: " + to_string(system.RunningProcesses())).c_str()); + ("Running Processes: " + to_string(system.RunningProcesses())).c_str(), ""); mvwprintw(window, ++row, 2, - ("Up Time: " + Format::ElapsedTime(system.UpTime())).c_str()); + ("Up Time: " + Format::ElapsedTime(system.UpTime())).c_str(), ""); wrefresh(window); } @@ -70,19 +72,21 @@ void NCursesDisplay::DisplayProcesses(std::vector& processes, mvwprintw(window, row, command_column, "COMMAND"); wattroff(window, COLOR_PAIR(2)); for (int i = 0; i < n; ++i) { - //You need to take care of the fact that the cpu utilization has already been multiplied by 100. - // Clear the line - mvwprintw(window, ++row, pid_column, (string(window->_maxx-2, ' ').c_str())); - - mvwprintw(window, row, pid_column, to_string(processes[i].Pid()).c_str()); - mvwprintw(window, row, user_column, processes[i].User().c_str()); + // You need to take care of the fact that the cpu utilization has already + // been multiplied by 100. + // Clear the line + mvwprintw(window, ++row, pid_column, + (string(window->_maxx - 2, ' ').c_str())); + + mvwprintw(window, row, pid_column, to_string(processes[i].Pid()).c_str(), ""); + mvwprintw(window, row, user_column, processes[i].User().c_str(), ""); float cpu = processes[i].CpuUtilization() * 100; - mvwprintw(window, row, cpu_column, to_string(cpu).substr(0, 4).c_str()); - mvwprintw(window, row, ram_column, processes[i].Ram().c_str()); + mvwprintw(window, row, cpu_column, to_string(cpu).substr(0, 4).c_str(), ""); + mvwprintw(window, row, ram_column, processes[i].Ram().c_str(), ""); mvwprintw(window, row, time_column, - Format::ElapsedTime(processes[i].UpTime()).c_str()); + Format::ElapsedTime(processes[i].UpTime()).c_str(), ""); mvwprintw(window, row, command_column, - processes[i].Command().substr(0, window->_maxx - 46).c_str()); + processes[i].Command().substr(0, window->_maxx - 46).c_str(), ""); } } diff --git a/src/process.cpp b/src/process.cpp index 82119905..8d3f865f 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -1,33 +1,115 @@ +#include "process.h" +#include "linux_parser.h" #include + #include #include #include #include -#include "process.h" - using std::string; using std::to_string; using std::vector; -// TODO: Return this process's ID -int Process::Pid() { return 0; } +Process::Process(int pid) : pid_{pid} +{ + keepAlive_ = true; + memUsage_ = ""; + cpuUsage_ = 0; + currentActiveJiffies_ = 0; + currentActiveJiffies_ = 0; + username_ = ""; + userInitialized_ = false; + command_ = ""; + commandInitialized_ = false; + upTime_ = 0; +} + +// DONE: Return this process's ID +int Process::Pid() { return pid_; } + +// DONE: Return this process's CPU utilization +float Process::CpuUtilization() { + if ((int)(cpuUsage_ * 1000) <= 0) + { + return 0; + } + else + { + return cpuUsage_; + } +} + +// DONE: Return the command that generated this process +string Process::Command() { + if (!commandInitialized_) + { + commandInitialized_ = true; + command_ = LinuxParser::Command(pid_); + } + return (command_); + } + +// DONE: Return this process's memory utilization +string Process::Ram() { + return (memUsage_); +} + +// DONE: Return the user (name) that generated this process +string Process::User() { + if(!userInitialized_) + { + userInitialized_ = true; + username_ = LinuxParser::User(pid_); + } + return username_; + } -// TODO: Return this process's CPU utilization -float Process::CpuUtilization() { return 0; } +// DONE: Return the age of this process (in seconds) +long int Process::UpTime() { return upTime_; } -// TODO: Return the command that generated this process -string Process::Command() { return string(); } +// DONE: Overload the "less than" comparison operator for Process objects +bool Process::operator<(Process const& a) const { + return ((int)(a.cpuUsage_*1000) < (int)(cpuUsage_*1000)); +} +bool Process::operator==(Process const& a) const { + return (pid_ == a.pid_); +} -// TODO: Return this process's memory utilization -string Process::Ram() { return string(); } +bool Process::KeepAlive() +{ + return keepAlive_; +} +void Process::KeepAlive(bool alive) +{ + keepAlive_ = alive; +} +void Process::updateCpuUsage(void) +{ + float previousActiveJiffies = currentActiveJiffies_; + float previousTotalJiffies = currentTotalJiffies_; + currentActiveJiffies_ = LinuxParser::ActiveJiffies(pid_); + currentTotalJiffies_ = LinuxParser::Jiffies(); + cpuUsage_ = (((currentActiveJiffies_ - previousActiveJiffies)/ (currentTotalJiffies_ - previousTotalJiffies))); +} -// TODO: Return the user (name) that generated this process -string Process::User() { return string(); } +void Process::updateMemUsage(void) +{ + if (memUsage_ == "") + { + string vMem = LinuxParser::Ram(pid_); + memUsage_ = std::to_string((std::stol(vMem)/1000)); + } +} -// TODO: Return the age of this process (in seconds) -long int Process::UpTime() { return 0; } +void Process::updateUpTime(){ + long rawUpTime = LinuxParser::UpTime(pid_); + upTime_ = rawUpTime/sysconf(_SC_CLK_TCK); +} -// TODO: Overload the "less than" comparison operator for Process objects -// REMOVE: [[maybe_unused]] once you define the function -bool Process::operator<(Process const& a[[maybe_unused]]) const { return true; } \ No newline at end of file +void Process::UpdateProcess() +{ + updateUpTime(); + updateCpuUsage(); + updateMemUsage(); +} \ No newline at end of file diff --git a/src/processor.cpp b/src/processor.cpp index 91662895..d633429f 100644 --- a/src/processor.cpp +++ b/src/processor.cpp @@ -1,4 +1,29 @@ +#include +#include + #include "processor.h" +#include "linux_parser.h" + +bool Processor::IsInitializied_ = false; -// TODO: Return the aggregate CPU utilization -float Processor::Utilization() { return 0.0; } \ No newline at end of file +Processor::Processor() +{ + CurrentTotalTime_ = 0.0; + CurrentRunTime_ = 0.0; +} +// DONE: Return the aggregate CPU utilization +float Processor::Utilization() { + LinuxParser::CpuUtilization(); + float PreviousTotalTime_ = CurrentTotalTime_; + float PreviousRunTime_ = CurrentRunTime_; + CurrentTotalTime_ = LinuxParser::Jiffies(); + CurrentRunTime_ = LinuxParser::ActiveJiffies(); + + if (!IsInitializied_) + { + IsInitializied_ = true; + return 0.0; + } + // TODO: [RH] handle overflow possibility + return ((CurrentRunTime_ - PreviousRunTime_))/((CurrentTotalTime_ - PreviousTotalTime_)); +} \ No newline at end of file diff --git a/src/system.cpp b/src/system.cpp index 98e53273..e07feec1 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -1,41 +1,123 @@ +#include "system.h" + #include + #include +#include #include #include #include +#include "linux_parser.h" #include "process.h" #include "processor.h" -#include "system.h" + using std::set; using std::size_t; using std::string; using std::vector; -/*You need to complete the mentioned TODOs in order to satisfy the rubric criteria "The student will be able to extract and display basic data about the system." +/*You need to complete the mentioned TODOs in order to satisfy the rubric +criteria "The student will be able to extract and display basic data about the +system." -You need to properly format the uptime. Refer to the comments mentioned in format. cpp for formatting the uptime.*/ +You need to properly format the uptime. Refer to the comments mentioned in +format. cpp for formatting the uptime.*/ -// TODO: Return the system's CPU +// DONE: Return the system's CPU Processor& System::Cpu() { return cpu_; } -// TODO: Return a container composed of the system's processes -vector& System::Processes() { return processes_; } +// DONE: Return a container composed of the system's processes +vector& System::Processes() { + vector processesPids = LinuxParser::Pids(); + System::updateSystemReadings(); + + for (auto& pid : processesPids) + { + auto it = std::find(processes_.begin(), processes_.end(), Process(pid)); + if(std::end(processes_) != it) + { + it->KeepAlive(true); + } + else + { + processes_.emplace_back(Process(pid)); + } + } + // LinuxParser::CpuUtilization(); + for (auto process = processes_.begin(); process != std::end(processes_);) + { + if (!(process->KeepAlive())) + { + processes_.erase(process); + } + else + { + process->UpdateProcess(); + process->KeepAlive(false); + ++process; + } + + } + std::sort(processes_.begin(), processes_.end(), [](auto& a, auto& b){ + return a < b; + }); + return processes_; +} + +// DONE: Return the system's kernel identifier (string) +std::string System::Kernel() { + if(!kernelRead_) + { + kernelRead_ = true; + systemKernel_ = LinuxParser::Kernel(); + } + return systemKernel_; +} + +// DONE: Return the system's memory utilization +float System::MemoryUtilization() { return memoryUtilization_; } -// TODO: Return the system's kernel identifier (string) -std::string System::Kernel() { return string(); } +// DONE: Return the operating system name +std::string System::OperatingSystem() { + if(!osRead_) + { + osRead_ = true; + systemOS_ = LinuxParser::Kernel(); + } + return systemOS_; +} -// TODO: Return the system's memory utilization -float System::MemoryUtilization() { return 0.0; } +// DONE: Return the number of processes actively running on the system +int System::RunningProcesses() { return runningProcesses_; } -// TODO: Return the operating system name -std::string System::OperatingSystem() { return string(); } +// DONE: Return the total number of processes on the system +int System::TotalProcesses() { return totalProcesses_; } -// TODO: Return the number of processes actively running on the system -int System::RunningProcesses() { return 0; } +// DONE: Return the number of seconds since the system started running +long int System::UpTime() { return upTime_; } -// TODO: Return the total number of processes on the system -int System::TotalProcesses() { return 0; } -// TODO: Return the number of seconds since the system started running -long int System::UpTime() { return 0; } +void System::updateSystemReadings() +{ + updateMemoryUtilization(); + updateUpTime(); + updateTotalProcesses(); + updateRunningProcesses(); +} +void System::updateMemoryUtilization() +{ + memoryUtilization_ = LinuxParser::MemoryUtilization(); +} +void System::updateUpTime() +{ + upTime_ = LinuxParser::UpTime(); +} +void System::updateTotalProcesses() +{ + totalProcesses_ = LinuxParser::TotalProcesses(); +} +void System::updateRunningProcesses() +{ + runningProcesses_ = LinuxParser::RunningProcesses(); +} \ No newline at end of file