1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <sys/types.h> 20 21 #include <string> 22 #include <string_view> 23 #include <vector> 24 25 #include "meminfo.h" 26 27 namespace android { 28 namespace meminfo { 29 30 using VmaCallback = std::function<void(const Vma&)>; 31 32 class ProcMemInfo final { 33 // Per-process memory accounting 34 public: 35 // Reset the working set accounting of the process via /proc/<pid>/clear_refs 36 static bool ResetWorkingSet(pid_t pid); 37 38 ProcMemInfo(pid_t pid, bool get_wss = false, uint64_t pgflags = 0, uint64_t pgflags_mask = 0); 39 40 const std::vector<Vma>& Maps(); 41 const MemUsage& Usage(); 42 const MemUsage& Wss(); 43 44 // Same as Maps() except, only valid for reading working set using CONFIG_IDLE_PAGE_TRACKING 45 // support in kernel. If the kernel support doesn't exist, the function will return an empty 46 // vector. 47 const std::vector<Vma>& MapsWithPageIdle(); 48 49 // Same as Maps() except, do not read the usage stats for each map. 50 const std::vector<Vma>& MapsWithoutUsageStats(); 51 52 // If MapsWithoutUsageStats was called, this function will fill in 53 // usage stats for this single vma. If 'use_kb' is true, the vma's 54 // usage will be populated in kilobytes instead of bytes. 55 bool FillInVmaStats(Vma& vma, bool use_kb = false); 56 57 // If ReadMaps (with get_usage_stats == false) or MapsWithoutUsageStats was 58 // called, this function will fill in usage stats for all vmas in 'maps_'. 59 bool GetUsageStats(bool get_wss, bool use_pageidle = false, bool swap_only = false); 60 61 // Collect all 'vma' or 'maps' from /proc/<pid>/smaps and store them in 'maps_'. If 62 // 'collect_usage' is 'true', this method will populate 'usage_' as vmas are being 63 // collected. Returns a constant reference to the vma vector after the collection is done. 64 // 65 // Each 'struct Vma' is *fully* populated by this method (unlike SmapsOrRollup). 66 const std::vector<Vma>& Smaps(const std::string& path = "", bool collect_usage = false); 67 68 // If 'use_smaps' is 'true' this method reads /proc/<pid>/smaps and calls the callback() 69 // for each vma or map that it finds, else if 'use_smaps' is false /proc/<pid>/maps is 70 // used instead. Each vma or map found, is converted to 'struct Vma' object which is then 71 // passed to the callback. 72 // Returns 'false' if the file is malformed. 73 bool ForEachVma(const VmaCallback& callback, bool use_smaps = true); 74 75 // Reads all VMAs from /proc/<pid>/maps and calls the callback() for each one of them. 76 // Returns false in case of failure during parsing. 77 bool ForEachVmaFromMaps(const VmaCallback& callback); 78 79 // Similar to other VMA reading methods, except this one allows passing a reusable buffer 80 // to store the /proc/<pid>/maps content 81 bool ForEachVmaFromMaps(const VmaCallback& callback, std::string& mapsBuffer); 82 83 // Takes the existing VMAs in 'maps_' and calls the callback() for each one 84 // of them. This is intended to avoid parsing /proc/<pid>/maps or 85 // /proc/<pid>/smaps twice. 86 // Returns false if 'maps_' is empty. 87 bool ForEachExistingVma(const VmaCallback& callback); 88 89 // Used to parse either of /proc/<pid>/{smaps, smaps_rollup} and record the process's 90 // Pss and Private memory usage in 'stats'. In particular, the method only populates the fields 91 // of the MemUsage structure that are intended to be used by Android's periodic Pss collection. 92 // 93 // The method populates the following statistics in order to be fast an efficient. 94 // Pss 95 // Rss 96 // Uss 97 // private_clean 98 // private_dirty 99 // SwapPss 100 // All other fields of MemUsage are zeroed. 101 bool SmapsOrRollup(MemUsage* stats) const; 102 103 // Used to parse either of /proc/<pid>/{smaps, smaps_rollup} and record the process's 104 // Pss. 105 // Returns 'true' on success and the value of Pss in the out parameter. 106 bool SmapsOrRollupPss(uint64_t* pss) const; 107 108 const std::vector<uint64_t>& SwapOffsets(); 109 110 // Reads /proc/<pid>/pagemap for this process for each page within 111 // the 'vma' and stores that in 'pagemap'. It is assumed that the 'vma' 112 // is obtained by calling Maps() or 'ForEachVma' for the same object. No special checks 113 // are made to see if 'vma' is *valid*. 114 // Returns false if anything goes wrong, 'true' otherwise. 115 bool PageMap(const Vma& vma, std::vector<uint64_t>* pagemap); 116 117 ~ProcMemInfo() = default; 118 119 private: 120 bool ReadMaps(bool get_wss, bool use_pageidle = false, bool get_usage_stats = true, 121 bool swap_only = false); 122 bool ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss, bool use_pageidle, bool swap_only); 123 124 pid_t pid_; 125 bool get_wss_; 126 uint64_t pgflags_; 127 uint64_t pgflags_mask_; 128 129 std::vector<Vma> maps_; 130 131 MemUsage usage_; 132 std::vector<uint64_t> swap_offsets_; 133 }; 134 135 // Makes callback for each 'vma' or 'map' found in file provided. 136 // If 'read_smaps_fields' is 'true', the file is expected to be in the 137 // same format as /proc/<pid>/smaps, else the file is expected to be 138 // formatted as /proc/<pid>/maps. 139 // Returns 'false' if the file is malformed. 140 bool ForEachVmaFromFile(const std::string& path, const VmaCallback& callback, 141 bool read_smaps_fields = true); 142 143 // Returns if the kernel supports /proc/<pid>/smaps_rollup. Assumes that the 144 // calling process has access to the /proc/<pid>/smaps_rollup. 145 // Returns 'false' if the file doesn't exist. 146 bool IsSmapsRollupSupported(); 147 148 // Same as ProcMemInfo::SmapsOrRollup but reads the statistics directly 149 // from a file. The file MUST be in the same format as /proc/<pid>/smaps 150 // or /proc/<pid>/smaps_rollup 151 bool SmapsOrRollupFromFile(const std::string& path, MemUsage* stats); 152 153 // Same as ProcMemInfo::SmapsOrRollupPss but reads the statistics directly 154 // from a file and returns total Pss in kB. The file MUST be in the same format 155 // as /proc/<pid>/smaps or /proc/<pid>/smaps_rollup 156 bool SmapsOrRollupPssFromFile(const std::string& path, uint64_t* pss); 157 158 // The output format that can be specified by user. 159 enum class Format { INVALID = 0, RAW, JSON, CSV }; 160 161 Format GetFormat(std::string_view arg); 162 163 std::string EscapeCsvString(const std::string& raw); 164 165 std::string EscapeJsonString(const std::string& raw); 166 167 } // namespace meminfo 168 } // namespace android 169