forked from udacity/CppND-System-Monitor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
linux_parser.cpp
287 lines (262 loc) · 9.93 KB
/
linux_parser.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
#include <dirent.h>
#include <unistd.h>
#include <sstream>
#include <string>
#include <vector>
#include "linux_parser.h"
#include "readFromFile.h"
#include "read_key_value.h"
using std::stof; // string to float
using std::string;
using std::to_string;
using std::vector;
// DONE: An example of how to read data from the filesystem
string LinuxParser::OperatingSystem() {
/* string line;
string key;
string value;
std::ifstream filestream(kOSPath);
if (filestream.is_open()) {
while (std::getline(filestream, line)) {
std::replace(line.begin(), line.end(), ' ', '_');
std::replace(line.begin(), line.end(), '=', ' ');
std::replace(line.begin(), line.end(), '"', ' ');
std::istringstream linestream(line);
while (linestream >> key >> value) {
if (key == "PRETTY_NAME") {
std::replace(value.begin(), value.end(), '_', ' ');
return value;
}
}
}
}
return value; */
std::string path_OS = "/etc/os-release";
std::string flag_OS = "PRETTY_NAME=";
std::string string_OS = readFromFile(path_OS,flag_OS);
return string_OS;
}
// DONE: An example of how to read data from the filesystem
string LinuxParser::Kernel() {
string os, kernel, version;
string line;
std::ifstream stream(kProcDirectory + kVersionFilename);
if (stream.is_open()) {
std::getline(stream, line);
std::istringstream linestream(line);
linestream >> os >> version >> kernel; // pop tokens from stream
}
return kernel;
}
// BONUS: Update this to use std::filesystem
// Pid = process IDs = integer foldernames in /proc
vector<int> LinuxParser::Pids() {
vector<int> pids;
DIR* directory = opendir(kProcDirectory.c_str());
struct dirent* file;
while ((file = readdir(directory)) != nullptr) {
// Is this a directory?
if (file->d_type == DT_DIR) {
// Is every character of the name a digit?
string filename(file->d_name);
if (std::all_of(filename.begin(), filename.end(), isdigit)) {
int pid = stoi(filename);
pids.push_back(pid);
}
}
}
closedir(directory);
return pids; // return vector of process IDs
}
// TODO: Read and return the system memory utilization
float LinuxParser::MemoryUtilization() {
float memUse, memTot, memFree, memBuffer, memCache, value;
std::ifstream fileStream(kProcDirectory + kMeminfoFilename);
string line, key, unit;
if (fileStream.is_open()) {
while(std::getline(fileStream,line)){ // get each line from fileStream
std::istringstream lineStream(line);
lineStream >> key >> value >> unit; // key and value separated by spaces, unit not used
if (key == "MemTotal:"){
memTot = value;}
if (key == "MemFree:"){
memFree = value;}
if (key == "Buffers:"){
memBuffer = value;}
if (key == "Cached:"){
memCache = value;}
}
}
memUse = (memTot - (memFree+memBuffer+memCache)) / memTot;
return memUse;}
// TODO: Read and return the total number of processes
int LinuxParser::TotalProcesses() {
float totProcesses, value;
std::ifstream fileStream(kProcDirectory + kStatFilename);
string line, key;
if (fileStream.is_open()) {
while(std::getline(fileStream,line)){ // get each line from fileStream
std::istringstream lineStream(line);
lineStream >> key >> value; // key and value separated by spaces
if (key == "processes"){
totProcesses = value;}
}
}
return totProcesses; }
// TODO: Read and return the number of running processes
int LinuxParser::RunningProcesses() {
float runProcesses, value;
std::ifstream fileStream(kProcDirectory + kStatFilename);
string line, key;
if (fileStream.is_open()) {
while(std::getline(fileStream,line)){ // get each line from fileStream
std::istringstream lineStream(line);
lineStream >> key >> value; // key and value separated by spaces
if (key == "procs_running"){
runProcesses = value;}
}
}
return runProcesses; }
// TODO: Read and return the system uptime
long LinuxParser::UpTime() {
long timeUpSeconds, timeIdleSeconds;
std::ifstream fileStream(kProcDirectory + kUptimeFilename);
string line, key;
if (fileStream.is_open()) {
std::getline(fileStream, line); // get line from fileStream
std::istringstream lineStream(line);
lineStream >> timeUpSeconds >> timeIdleSeconds;
}
return timeUpSeconds; }
/* // TODO: Read and return the number of jiffies for the system
// tick rate = clock frequency in Hz = declared in include/asm-i386/param.h
// Jiffies = number of ticks since system booted = declared in <linux/jiffies.h>
// seconds = (jiffies / Hz)
long LinuxParser::Jiffies() { return 0; }
// 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; }
// TODO: Read and return the number of active jiffies for the system
long LinuxParser::ActiveJiffies() { return 0; }
// TODO: Read and return the number of idle jiffies for the system
long LinuxParser::IdleJiffies() { return 0; } */
// TODO: Read and return CPU utilization
vector<string> LinuxParser::CpuUtilization() {
// initialize output
vector<string> cpu_vector;
string key, user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice;
// access file /proc/stat from namespace LinuxParser
std::ifstream fileStream(kProcDirectory + kStatFilename);
std::string line;
if(fileStream.is_open()){
while(std::getline(fileStream,line)){
std::istringstream lineStream(line);
lineStream >> key >> user >> nice >> system >> idle >> iowait >> irq >> softirq >> steal >> guest >> guest_nice;
if(key == "cpu"){
cpu_vector.push_back(user);
cpu_vector.push_back(nice);
cpu_vector.push_back(system);
cpu_vector.push_back(idle);
cpu_vector.push_back(iowait);
cpu_vector.push_back(irq);
cpu_vector.push_back(softirq);
cpu_vector.push_back(steal);
cpu_vector.push_back(guest);
cpu_vector.push_back(guest_nice);
}
}
}
return cpu_vector; }
// Processor Utilization of individual PID, overloaded with overall CpuUtilization
// CPU utilization of a process stored in /proc/[PID]/stat
float LinuxParser::CpuUtilization(int pid) {
string stat_int;
string pid_str = to_string(pid);
vector<string> PID_stat_vector;
int utime,stime,starttime,totaltime;
long int uptime = LinuxParser::UpTime(); // [seconds]
float time_seconds, cpu_percent{0.0};
int freq = sysconf(_SC_CLK_TCK); // [Hz]
std::ifstream filestream(kProcDirectory + pid_str + kStatFilename);
if(filestream.is_open()){
while (filestream >> stat_int){
PID_stat_vector.push_back(stat_int);
} // https://man7.org/linux/man-pages/man5/proc.5.html
utime = std::stoi(PID_stat_vector[13]); // time of process in user mode [clock ticks]
stime = std::stoi(PID_stat_vector[14]); // time of process in kernel mode [clock ticks]
starttime = std::stoi(PID_stat_vector[21]); // time of process after boot [clock ticks]
totaltime = (utime + stime)/freq; // [seconds]
time_seconds = uptime - (starttime/freq); // [seconds]
cpu_percent = totaltime / time_seconds;
}
return cpu_percent;}
// TODO: Read and return the command associated with a process
// command to launch a PID in /proc/[pid]/cmdline
string LinuxParser::Command(int pid) {
string pid_str = to_string(pid); // create filestream of PID path to get PID command
std::ifstream filestream(kProcDirectory + pid_str + kCmdlineFilename);
string line, command; // parse command from linestream
if (filestream.is_open()) {
while (std::getline(filestream, line)) {
std::istringstream linestream(line);
linestream >> command;
}
}
return command; }
// TODO: Read and return the memory used by a process
string LinuxParser::Ram(int pid) {
string pid_str = to_string(pid); // path to PID status
string path = kProcDirectory + pid_str + kStatusFilename;
string target_key = "VmRSS:"; // get value by key
string memory = read_key_value(path, target_key);
return memory;
}
// TODO: Read and return the user ID associated with a process
string LinuxParser::Uid(int pid) {
string pid_str = to_string(pid); // path to PID status
string path = kProcDirectory + pid_str + kStatusFilename;
string target_key = "Uid:"; // get value by key
string uid = read_key_value(path, target_key);
return uid;
}
// TODO: Read and return the user associated with a process
string LinuxParser::User(int pid) {
string line, username, name_str, x, uid_str;
// string pidNum = to_string(pid);
std::ifstream filestream(kPasswordPath);
if (filestream.is_open()) {
while (std::getline(filestream, line)) {
// to use linestream, ensure delimeter = space ' '
std::replace(line.begin(), line.end(), ':', ' ');
std::istringstream linestream(line);
while (linestream >> name_str >> x >> uid_str) {
if (uid_str == LinuxParser::Uid(pid)) {
username = name_str;
}
}
}
}
return username;
}
// TODO: Read and return the uptime of a process
// UpTime = time since process started after system boot
// overloaded with overall Up Time
// starttime %llu
// before Linux 2.6, this value was expressed in jiffies
// since Linux 2.6, this value is expressed in clock ticks
long LinuxParser::UpTime(int pid) {
long process_time_seconds{0};
int freq = sysconf(_SC_CLK_TCK); // [Hz]
string line, start_time;
string pid_str = to_string(pid);
std::ifstream filestream(kProcDirectory + pid_str + kStatFilename);
if (filestream.is_open()) {
std::getline(filestream, line);
std::istringstream linestream(line);
for (int i = 0; i<22; ++i){ // get process start time on position 21
linestream >> start_time;
}
}
process_time_seconds = LinuxParser::UpTime() - std::stol(start_time)/freq;
return process_time_seconds;
}