From 01216f3c3fb0cd763adbc441fa728ffd5a2c254f Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 10 Jul 2019 13:56:28 +0200 Subject: [PATCH] Userland+LibCore: Use CProcessStatisticsReader to implement top. Also tweaked CProcessStatisticsReader a bit to simplify the API. --- .../LibCore/CProcessStatisticsReader.cpp | 40 +++++------ Libraries/LibCore/CProcessStatisticsReader.h | 9 +-- Userland/killall.cpp | 2 +- Userland/pidof.cpp | 2 +- Userland/top.cpp | 71 ++++++++----------- 5 files changed, 52 insertions(+), 72 deletions(-) diff --git a/Libraries/LibCore/CProcessStatisticsReader.cpp b/Libraries/LibCore/CProcessStatisticsReader.cpp index 7f0456d53e4..30da9a1f53a 100644 --- a/Libraries/LibCore/CProcessStatisticsReader.cpp +++ b/Libraries/LibCore/CProcessStatisticsReader.cpp @@ -6,27 +6,16 @@ #include #include -CProcessStatisticsReader::CProcessStatisticsReader() -{ - setpwent(); - while (auto* passwd = getpwent()) - m_usernames.set(passwd->pw_uid, passwd->pw_name); - endpwent(); -} +HashMap CProcessStatisticsReader::s_usernames; -HashMap CProcessStatisticsReader::get_map() +HashMap CProcessStatisticsReader::get_all() { - HashMap res; - update_map(res); - return res; -} + HashMap map; -void CProcessStatisticsReader::update_map(HashMap& map) -{ CFile file("/proc/all"); if (!file.open(CIODevice::ReadOnly)) { fprintf(stderr, "CProcessHelper : failed to open /proc/all: %s\n", file.error_string()); - return; + return {}; } auto file_contents = file.read_all(); @@ -37,7 +26,7 @@ void CProcessStatisticsReader::update_map(HashMap& ma process.pid = process_object.get("pid").to_u32(); process.nsched = process_object.get("times_scheduled").to_u32(); process.uid = process_object.get("uid").to_u32(); - process.username = get_username_from_uid(process.uid); + process.username = username_from_uid(process.uid); process.priority = process_object.get("priority").to_string(); process.syscalls = process_object.get("syscall_count").to_u32(); process.state = process_object.get("state").to_string(); @@ -46,13 +35,22 @@ void CProcessStatisticsReader::update_map(HashMap& ma process.physical_size = process_object.get("amount_resident").to_u32(); map.set(process.pid, process); }); + + return map; } -String CProcessStatisticsReader::get_username_from_uid(const uid_t uid) +String CProcessStatisticsReader::username_from_uid(uid_t uid) { - auto it = m_usernames.find(uid); - if (it != m_usernames.end()) + if (s_usernames.is_empty()) { + setpwent(); + while (auto* passwd = getpwent()) + s_usernames.set(passwd->pw_uid, passwd->pw_name); + endpwent(); + } + + auto it = s_usernames.find(uid); + if (it != s_usernames.end()) return (*it).value; - else - return String::number(uid); + return String::number(uid); } + diff --git a/Libraries/LibCore/CProcessStatisticsReader.h b/Libraries/LibCore/CProcessStatisticsReader.h index adb96f39ad8..c26312bc890 100644 --- a/Libraries/LibCore/CProcessStatisticsReader.h +++ b/Libraries/LibCore/CProcessStatisticsReader.h @@ -18,12 +18,9 @@ struct CProcessStatistics { class CProcessStatisticsReader { public: - CProcessStatisticsReader(); - HashMap get_map(); + static HashMap get_all(); private: - void update_map(HashMap& map); - String get_username_from_uid(const uid_t uid); - - HashMap m_usernames; + static String username_from_uid(uid_t); + static HashMap s_usernames; }; diff --git a/Userland/killall.cpp b/Userland/killall.cpp index 85594d8ea8f..fcc4b79cb15 100644 --- a/Userland/killall.cpp +++ b/Userland/killall.cpp @@ -13,7 +13,7 @@ static void print_usage_and_exit() static int kill_all(const String& process_name, const unsigned signum) { - HashMap processes = CProcessStatisticsReader().get_map(); + auto processes = CProcessStatisticsReader().get_all(); for (auto& it : processes) { if (it.value.name == process_name) { diff --git a/Userland/pidof.cpp b/Userland/pidof.cpp index a115d9deb15..e1aa005e291 100644 --- a/Userland/pidof.cpp +++ b/Userland/pidof.cpp @@ -12,7 +12,7 @@ static int pid_of(const String& process_name, bool single_shot, bool omit_pid, p { bool displayed_at_least_one = false; - HashMap processes = CProcessStatisticsReader().get_map(); + auto processes = CProcessStatisticsReader().get_all(); for (auto& it : processes) { if (it.value.name == process_name) { diff --git a/Userland/top.cpp b/Userland/top.cpp index 5ddfa7edbfd..f78486c0f95 100644 --- a/Userland/top.cpp +++ b/Userland/top.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -14,22 +15,15 @@ static HashMap* s_usernames; -struct Process { - pid_t pid; - unsigned nsched; - String name; - String state; - String user; - String priority; - unsigned virtual_size; - unsigned physical_size; - unsigned nsched_since_prev; - unsigned cpu_percent; - unsigned cpu_percent_decimal; +struct ProcessData { + CProcessStatistics stats; + unsigned nsched_since_prev { 0 }; + unsigned cpu_percent { 0 }; + unsigned cpu_percent_decimal { 0 }; }; struct Snapshot { - HashMap map; + HashMap map; u32 sum_nsched { 0 }; }; @@ -43,25 +37,16 @@ static Snapshot get_snapshot() Snapshot snapshot; - auto file_contents = file.read_all(); - auto json = JsonValue::from_string({ file_contents.data(), file_contents.size() }); - json.as_array().for_each([&](auto& value) { - const JsonObject& process_object = value.as_object(); - pid_t pid = process_object.get("pid").to_u32(); - unsigned nsched = process_object.get("times_scheduled").to_u32(); - snapshot.sum_nsched += nsched; - Process process; - process.pid = pid; - process.nsched = nsched; - unsigned uid = process_object.get("uid").to_u32(); - process.user = s_usernames->get(uid); - process.priority = process_object.get("priority").to_string(); - process.state = process_object.get("state").to_string(); - process.name = process_object.get("name").to_string(); - process.virtual_size = process_object.get("amount_virtual").to_u32(); - process.physical_size = process_object.get("amount_resident").to_u32(); - snapshot.map.set(pid, move(process)); - }); + auto all_processes = CProcessStatisticsReader::get_all(); + + for (auto& it : all_processes) { + auto& stats = it.value; + snapshot.sum_nsched += stats.nsched; + ProcessData process_data; + process_data.stats = stats; + snapshot.map.set(stats.pid, move(process_data)); + } + return snapshot; } @@ -73,7 +58,7 @@ int main(int, char**) s_usernames->set(passwd->pw_uid, passwd->pw_name); endpwent(); - Vector processes; + Vector processes; auto prev = get_snapshot(); usleep(10000); for (;;) { @@ -94,11 +79,11 @@ int main(int, char**) pid_t pid = it.key; if (pid == 0) continue; - u32 nsched_now = it.value.nsched; + u32 nsched_now = it.value.stats.nsched; auto jt = prev.map.find(pid); if (jt == prev.map.end()) continue; - u32 nsched_before = (*jt).value.nsched; + u32 nsched_before = (*jt).value.stats.nsched; u32 nsched_diff = nsched_now - nsched_before; it.value.nsched_since_prev = nsched_diff; it.value.cpu_percent = ((nsched_diff * 100) / sum_diff); @@ -111,16 +96,16 @@ int main(int, char**) }); for (auto* process : processes) { - printf("%6d %c %-8s %-8s %6u %6u %2u.%1u %s\n", - process->pid, - process->priority[0], - process->user.characters(), - process->state.characters(), - process->virtual_size / 1024, - process->physical_size / 1024, + printf("%6d %c %-8s %-8s %6zu %6zu %2u.%1u %s\n", + process->stats.pid, + process->stats.priority[0], + process->stats.username.characters(), + process->stats.state.characters(), + process->stats.virtual_size / 1024, + process->stats.physical_size / 1024, process->cpu_percent, process->cpu_percent_decimal, - process->name.characters()); + process->stats.name.characters()); } processes.clear_with_capacity(); prev = move(current);