OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "procfs_utils.h" |
| 6 |
| 7 #include <stdio.h> |
| 8 #include <string.h> |
| 9 |
| 10 #include "file_utils.h" |
| 11 #include "logging.h" |
| 12 |
| 13 using file_utils::ForEachPidInProcPath; |
| 14 using file_utils::ReadProcFile; |
| 15 using file_utils::ReadProcFileTrimmed; |
| 16 |
| 17 namespace procfs_utils { |
| 18 |
| 19 namespace { |
| 20 |
| 21 const char kJavaAppPrefix[] = "/system/bin/app_process"; |
| 22 const char kZygotePrefix[] = "zygote"; |
| 23 |
| 24 inline void ReadProcString(int pid, const char* path, char* buf, size_t size) { |
| 25 if (!file_utils::ReadProcFileTrimmed(pid, path, buf, size)) |
| 26 buf[0] = '\0'; |
| 27 } |
| 28 |
| 29 inline void ReadExePath(int pid, char* buf, size_t size) { |
| 30 char exe_path[64]; |
| 31 sprintf(exe_path, "/proc/%d/exe", pid); |
| 32 ssize_t res = readlink(exe_path, buf, size - 1); |
| 33 if (res >= 0) |
| 34 buf[res] = '\0'; |
| 35 else |
| 36 buf[0] = '\0'; |
| 37 } |
| 38 |
| 39 inline bool IsApp(const char* name, const char* exe) { |
| 40 return strncmp(exe, kJavaAppPrefix, sizeof(kJavaAppPrefix) - 1) == 0 && |
| 41 strncmp(name, kZygotePrefix, sizeof(kZygotePrefix) - 1) != 0; |
| 42 } |
| 43 |
| 44 } // namespace |
| 45 |
| 46 int ReadTgid(int pid) { |
| 47 static const char kTgid[] = "\nTgid:"; |
| 48 char buf[512]; |
| 49 ssize_t rsize = ReadProcFile(pid, "status", buf, sizeof(buf)); |
| 50 if (rsize <= 0) |
| 51 return -1; |
| 52 const char* tgid_line = strstr(buf, kTgid); |
| 53 CHECK(tgid_line); |
| 54 return atoi(tgid_line + sizeof(kTgid) - 1); |
| 55 } |
| 56 |
| 57 std::unique_ptr<ProcessInfo> ReadProcessInfo(int pid) { |
| 58 ProcessInfo* process = new ProcessInfo(); |
| 59 process->pid = pid; |
| 60 ReadProcString(pid, "cmdline", process->name, sizeof(process->name)); |
| 61 if (process->name[0] != 0) { |
| 62 ReadExePath(pid, process->exe, sizeof(process->exe)); |
| 63 process->is_app = IsApp(process->name, process->exe); |
| 64 } else { |
| 65 ReadProcString(pid, "comm", process->name, sizeof(process->name)); |
| 66 CHECK(process->name[0]); |
| 67 process->in_kernel = true; |
| 68 } |
| 69 return std::unique_ptr<ProcessInfo>(process); |
| 70 } |
| 71 |
| 72 void ReadProcessThreads(ProcessInfo* process) { |
| 73 if (process->in_kernel) |
| 74 return; |
| 75 |
| 76 char tasks_path[64]; |
| 77 sprintf(tasks_path, "/proc/%d/task", process->pid); |
| 78 ForEachPidInProcPath(tasks_path, [process](int tid) { |
| 79 if (process->threads.count(tid)) |
| 80 return; |
| 81 ThreadInfo thread = { tid, "" }; |
| 82 char task_comm[64]; |
| 83 sprintf(task_comm, "task/%d/comm", tid); |
| 84 ReadProcString(process->pid, task_comm, thread.name, sizeof(thread.name)); |
| 85 if (thread.name[0] == '\0' && process->is_app) |
| 86 strcpy(thread.name, "UI Thread"); |
| 87 process->threads[tid] = thread; |
| 88 }); |
| 89 } |
| 90 |
| 91 bool ReadOomStats(ProcessSnapshot* snapshot) { |
| 92 char buf[64]; |
| 93 if (ReadProcFileTrimmed(snapshot->pid, "oom_score", buf, sizeof(buf))) |
| 94 snapshot->oom_score = atoi(buf); |
| 95 else |
| 96 return false; |
| 97 if (ReadProcFileTrimmed(snapshot->pid, "oom_score_adj", buf, sizeof(buf))) |
| 98 snapshot->oom_score_adj = atoi(buf); |
| 99 else |
| 100 return false; |
| 101 return true; |
| 102 } |
| 103 |
| 104 bool ReadPageFaultsAndCpuTimeStats(ProcessSnapshot* snapshot) { |
| 105 char buf[512]; |
| 106 if (!ReadProcFileTrimmed(snapshot->pid, "stat", buf, sizeof(buf))) |
| 107 return false; |
| 108 int ret = sscanf(buf, |
| 109 "%*d (%*[^)]) %*c %*d %*d %*d %*d %*d %*u %lu %*lu %lu %*lu %lu %lu", |
| 110 &snapshot->minor_faults, &snapshot->major_faults, |
| 111 &snapshot->utime, &snapshot->stime); |
| 112 CHECK(ret == 4); |
| 113 return true; |
| 114 } |
| 115 |
| 116 |
| 117 } // namespace procfs_utils |
OLD | NEW |