1ba5c3796Sopenharmony_ci/* 2ba5c3796Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3ba5c3796Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4ba5c3796Sopenharmony_ci * you may not use this file except in compliance with the License. 5ba5c3796Sopenharmony_ci * You may obtain a copy of the License at 6ba5c3796Sopenharmony_ci * 7ba5c3796Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8ba5c3796Sopenharmony_ci * 9ba5c3796Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10ba5c3796Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11ba5c3796Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12ba5c3796Sopenharmony_ci * See the License for the specific language governing permissions and 13ba5c3796Sopenharmony_ci * limitations under the License. 14ba5c3796Sopenharmony_ci */ 15ba5c3796Sopenharmony_ci 16ba5c3796Sopenharmony_ci#include "kernel_interface.h" 17ba5c3796Sopenharmony_ci 18ba5c3796Sopenharmony_ci#include <climits> 19ba5c3796Sopenharmony_ci#include <csignal> 20ba5c3796Sopenharmony_ci#include <dirent.h> 21ba5c3796Sopenharmony_ci#include <fstream> 22ba5c3796Sopenharmony_ci#include <regex> 23ba5c3796Sopenharmony_ci#include <securec.h> 24ba5c3796Sopenharmony_ci#include <sstream> 25ba5c3796Sopenharmony_ci#include <sys/stat.h> 26ba5c3796Sopenharmony_ci#include <unistd.h> 27ba5c3796Sopenharmony_ci 28ba5c3796Sopenharmony_ci#include "directory_ex.h" 29ba5c3796Sopenharmony_ci#include "file_ex.h" 30ba5c3796Sopenharmony_ci#include "memmgr_log.h" 31ba5c3796Sopenharmony_ci 32ba5c3796Sopenharmony_cinamespace OHOS { 33ba5c3796Sopenharmony_cinamespace Memory { 34ba5c3796Sopenharmony_cinamespace { 35ba5c3796Sopenharmony_ciconst std::string TAG = "KernelInterface"; 36ba5c3796Sopenharmony_ci} 37ba5c3796Sopenharmony_ci 38ba5c3796Sopenharmony_ciIMPLEMENT_SINGLE_INSTANCE(KernelInterface); 39ba5c3796Sopenharmony_ci 40ba5c3796Sopenharmony_ciconst std::string KernelInterface::ROOT_PROC_PATH = "/proc"; 41ba5c3796Sopenharmony_ciconst std::string KernelInterface::MEMCG_BASE_PATH = "/dev/memcg"; 42ba5c3796Sopenharmony_ciconst std::string KernelInterface::FILE_MEMCG_PROCS = "cgroup.procs"; 43ba5c3796Sopenharmony_ci 44ba5c3796Sopenharmony_ci#ifdef USE_HYPERHOLD_MEMORY 45ba5c3796Sopenharmony_ciconst std::string KernelInterface::ZWAPD_PRESSURE_SHOW_PATH = "/dev/memcg/memory.zswapd_pressure_show"; 46ba5c3796Sopenharmony_ciconst std::string KernelInterface::ZWAPD_PRESSURE_SHOW_BUFFER_SIZE = "buffer_size"; 47ba5c3796Sopenharmony_ci#else 48ba5c3796Sopenharmony_ciconst std::string KernelInterface::ZWAPD_PRESSURE_SHOW_PATH = "/proc/meminfo"; 49ba5c3796Sopenharmony_ciconst std::string KernelInterface::ZWAPD_PRESSURE_SHOW_BUFFER_SIZE = "MemAvailable"; 50ba5c3796Sopenharmony_ci#endif 51ba5c3796Sopenharmony_ciconst std::string KernelInterface::MEMINFO_PATH = "/proc/meminfo"; 52ba5c3796Sopenharmony_ciconst std::string KernelInterface::FILE_PROC_STATUS = "status"; 53ba5c3796Sopenharmony_ciconst std::string KernelInterface::TOTAL_MEMORY = "MemTotal"; 54ba5c3796Sopenharmony_ci 55ba5c3796Sopenharmony_cibool KernelInterface::EchoToPath(const char* path, const char* content) 56ba5c3796Sopenharmony_ci{ 57ba5c3796Sopenharmony_ci int fd = open(path, O_WRONLY); 58ba5c3796Sopenharmony_ci if (fd == -1) { 59ba5c3796Sopenharmony_ci HILOGE("echo %{public}s > %{public}s failed: file is not open", content, path); 60ba5c3796Sopenharmony_ci return false; 61ba5c3796Sopenharmony_ci } 62ba5c3796Sopenharmony_ci if (write(fd, content, strlen(content)) < 0) { 63ba5c3796Sopenharmony_ci HILOGE("echo %{public}s > %{public}s failed: write failed", content, path); 64ba5c3796Sopenharmony_ci close(fd); 65ba5c3796Sopenharmony_ci return false; 66ba5c3796Sopenharmony_ci } 67ba5c3796Sopenharmony_ci close(fd); 68ba5c3796Sopenharmony_ci HILOGI("echo %{public}s > %{public}s", content, path); 69ba5c3796Sopenharmony_ci return true; 70ba5c3796Sopenharmony_ci} 71ba5c3796Sopenharmony_ci 72ba5c3796Sopenharmony_cibool KernelInterface::IsFileExists(const std::string& path) 73ba5c3796Sopenharmony_ci{ 74ba5c3796Sopenharmony_ci if (path.empty()) { 75ba5c3796Sopenharmony_ci return false; 76ba5c3796Sopenharmony_ci } 77ba5c3796Sopenharmony_ci struct stat st = {}; 78ba5c3796Sopenharmony_ci if (stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode)) { 79ba5c3796Sopenharmony_ci return true; 80ba5c3796Sopenharmony_ci } 81ba5c3796Sopenharmony_ci return false; 82ba5c3796Sopenharmony_ci} 83ba5c3796Sopenharmony_ci 84ba5c3796Sopenharmony_cibool KernelInterface::CreateFile(const std::string& path, const mode_t& mode) 85ba5c3796Sopenharmony_ci{ 86ba5c3796Sopenharmony_ci if (path.empty()) { 87ba5c3796Sopenharmony_ci return false; 88ba5c3796Sopenharmony_ci } 89ba5c3796Sopenharmony_ci if (IsFileExists(path)) { 90ba5c3796Sopenharmony_ci return true; 91ba5c3796Sopenharmony_ci } 92ba5c3796Sopenharmony_ci 93ba5c3796Sopenharmony_ci std::ofstream fout(path); 94ba5c3796Sopenharmony_ci if (!fout.is_open()) { 95ba5c3796Sopenharmony_ci return false; 96ba5c3796Sopenharmony_ci } 97ba5c3796Sopenharmony_ci fout.flush(); 98ba5c3796Sopenharmony_ci fout.close(); 99ba5c3796Sopenharmony_ci if (chmod(path.c_str(), mode) != 0) { 100ba5c3796Sopenharmony_ci return false; 101ba5c3796Sopenharmony_ci } 102ba5c3796Sopenharmony_ci 103ba5c3796Sopenharmony_ci return true; 104ba5c3796Sopenharmony_ci} 105ba5c3796Sopenharmony_ci 106ba5c3796Sopenharmony_cibool KernelInterface::CreateFile(const std::string& path) 107ba5c3796Sopenharmony_ci{ 108ba5c3796Sopenharmony_ci return CreateFile(path, FILE_MODE_644); 109ba5c3796Sopenharmony_ci} 110ba5c3796Sopenharmony_ci 111ba5c3796Sopenharmony_cibool KernelInterface::RemoveFile(const std::string& path) 112ba5c3796Sopenharmony_ci{ 113ba5c3796Sopenharmony_ci return OHOS::RemoveFile(path); 114ba5c3796Sopenharmony_ci} 115ba5c3796Sopenharmony_ci 116ba5c3796Sopenharmony_cibool KernelInterface::WriteToFile(const std::string& path, const std::string& content, bool truncated) 117ba5c3796Sopenharmony_ci{ 118ba5c3796Sopenharmony_ci int fd; 119ba5c3796Sopenharmony_ci char actualPath[PATH_MAX + 1] = {0}; 120ba5c3796Sopenharmony_ci char* ptrRet = NULL; 121ba5c3796Sopenharmony_ci 122ba5c3796Sopenharmony_ci if (strlen(path.c_str()) == 0 || strlen(path.c_str()) > PATH_MAX) { 123ba5c3796Sopenharmony_ci HILOGE("file path is invalid"); 124ba5c3796Sopenharmony_ci return false; 125ba5c3796Sopenharmony_ci } 126ba5c3796Sopenharmony_ci ptrRet = realpath(path.c_str(), actualPath); 127ba5c3796Sopenharmony_ci if (!ptrRet) { 128ba5c3796Sopenharmony_ci HILOGE("file path cannot be canonicalized"); 129ba5c3796Sopenharmony_ci return false; 130ba5c3796Sopenharmony_ci } 131ba5c3796Sopenharmony_ci HILOGD("path:%{public}s, actualPath:%{public}s", path.c_str(), actualPath); 132ba5c3796Sopenharmony_ci fd = open(actualPath, O_RDWR | (truncated ? O_TRUNC : O_APPEND)); 133ba5c3796Sopenharmony_ci if (fd == -1) { 134ba5c3796Sopenharmony_ci HILOGE("echo %{public}s %{public}s %{public}s failed: file is not open", 135ba5c3796Sopenharmony_ci content.c_str(), truncated ? ">" : ">>", path.c_str()); 136ba5c3796Sopenharmony_ci ptrRet = NULL; 137ba5c3796Sopenharmony_ci return false; 138ba5c3796Sopenharmony_ci } 139ba5c3796Sopenharmony_ci if (write(fd, content.c_str(), strlen(content.c_str())) < 0) { 140ba5c3796Sopenharmony_ci HILOGE("echo %{public}s %{public}s %{public}s failed: write failed", 141ba5c3796Sopenharmony_ci content.c_str(), truncated ? ">" : ">>", path.c_str()); 142ba5c3796Sopenharmony_ci ptrRet = NULL; 143ba5c3796Sopenharmony_ci close(fd); 144ba5c3796Sopenharmony_ci return false; 145ba5c3796Sopenharmony_ci } 146ba5c3796Sopenharmony_ci ptrRet = NULL; 147ba5c3796Sopenharmony_ci close(fd); 148ba5c3796Sopenharmony_ci HILOGD("echo %{public}s %{public}s %{public}s", content.c_str(), truncated ? ">" : ">>", path.c_str()); 149ba5c3796Sopenharmony_ci return true; 150ba5c3796Sopenharmony_ci} 151ba5c3796Sopenharmony_ci 152ba5c3796Sopenharmony_cibool KernelInterface::ReadFromFile(const std::string& path, std::string& content) 153ba5c3796Sopenharmony_ci{ 154ba5c3796Sopenharmony_ci return OHOS::LoadStringFromFile(path, content); 155ba5c3796Sopenharmony_ci} 156ba5c3796Sopenharmony_ci 157ba5c3796Sopenharmony_cibool KernelInterface::ReadLinesFromFile(const std::string& path, std::vector<std::string>& lines) 158ba5c3796Sopenharmony_ci{ 159ba5c3796Sopenharmony_ci if (!IsFileExists(path)) { 160ba5c3796Sopenharmony_ci HILOGE("no such file: %{public}s", path.c_str()); 161ba5c3796Sopenharmony_ci return false; 162ba5c3796Sopenharmony_ci } 163ba5c3796Sopenharmony_ci std::string line; 164ba5c3796Sopenharmony_ci std::ifstream inf(path, std::ifstream::in); 165ba5c3796Sopenharmony_ci if (!inf) { 166ba5c3796Sopenharmony_ci HILOGE("ifstream(%{public}s) failed", path.c_str()); 167ba5c3796Sopenharmony_ci return false; 168ba5c3796Sopenharmony_ci } 169ba5c3796Sopenharmony_ci lines.clear(); 170ba5c3796Sopenharmony_ci while (!inf.eof()) { 171ba5c3796Sopenharmony_ci getline(inf, line); 172ba5c3796Sopenharmony_ci lines.push_back(line); 173ba5c3796Sopenharmony_ci } 174ba5c3796Sopenharmony_ci inf.close(); 175ba5c3796Sopenharmony_ci return true; 176ba5c3796Sopenharmony_ci} 177ba5c3796Sopenharmony_ci 178ba5c3796Sopenharmony_cibool KernelInterface::IsDirExists(const std::string& path) 179ba5c3796Sopenharmony_ci{ 180ba5c3796Sopenharmony_ci if (path.empty()) { 181ba5c3796Sopenharmony_ci return false; 182ba5c3796Sopenharmony_ci } 183ba5c3796Sopenharmony_ci struct stat st = {}; 184ba5c3796Sopenharmony_ci if (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) { 185ba5c3796Sopenharmony_ci return true; 186ba5c3796Sopenharmony_ci } 187ba5c3796Sopenharmony_ci return false; 188ba5c3796Sopenharmony_ci} 189ba5c3796Sopenharmony_ci 190ba5c3796Sopenharmony_ciint64_t KernelInterface::GetSystemCurTime() 191ba5c3796Sopenharmony_ci{ 192ba5c3796Sopenharmony_ci return std::chrono::duration_cast<std::chrono::milliseconds> 193ba5c3796Sopenharmony_ci (std::chrono::system_clock::now().time_since_epoch()).count(); 194ba5c3796Sopenharmony_ci} 195ba5c3796Sopenharmony_ci 196ba5c3796Sopenharmony_ciint64_t KernelInterface::GetSystemTimeMs() 197ba5c3796Sopenharmony_ci{ 198ba5c3796Sopenharmony_ci return std::chrono::duration_cast<std::chrono::seconds> 199ba5c3796Sopenharmony_ci (std::chrono::system_clock::now().time_since_epoch()).count(); 200ba5c3796Sopenharmony_ci} 201ba5c3796Sopenharmony_ci 202ba5c3796Sopenharmony_cibool KernelInterface::IsExists(const std::string& path) 203ba5c3796Sopenharmony_ci{ 204ba5c3796Sopenharmony_ci return OHOS::FileExists(path); 205ba5c3796Sopenharmony_ci} 206ba5c3796Sopenharmony_ci 207ba5c3796Sopenharmony_cibool KernelInterface::IsEmptyDir(const std::string& path) 208ba5c3796Sopenharmony_ci{ 209ba5c3796Sopenharmony_ci return OHOS::IsEmptyFolder(path); 210ba5c3796Sopenharmony_ci} 211ba5c3796Sopenharmony_ci 212ba5c3796Sopenharmony_cibool KernelInterface::CreateDir(const std::string& path) 213ba5c3796Sopenharmony_ci{ 214ba5c3796Sopenharmony_ci return OHOS::ForceCreateDirectory(path); // default mode 755 215ba5c3796Sopenharmony_ci} 216ba5c3796Sopenharmony_ci 217ba5c3796Sopenharmony_cibool KernelInterface::RemoveDirRecursively(const std::string& path) 218ba5c3796Sopenharmony_ci{ 219ba5c3796Sopenharmony_ci return OHOS::ForceRemoveDirectory(path) || (remove(path.c_str()) == 0); 220ba5c3796Sopenharmony_ci} 221ba5c3796Sopenharmony_ci 222ba5c3796Sopenharmony_cistd::string KernelInterface::RmDelimiter(const std::string& path) 223ba5c3796Sopenharmony_ci{ 224ba5c3796Sopenharmony_ci if (path.empty()) { 225ba5c3796Sopenharmony_ci return path; 226ba5c3796Sopenharmony_ci } 227ba5c3796Sopenharmony_ci return OHOS::ExcludeTrailingPathDelimiter(path); 228ba5c3796Sopenharmony_ci} 229ba5c3796Sopenharmony_ci 230ba5c3796Sopenharmony_cistd::string KernelInterface::AddDelimiter(const std::string& path) 231ba5c3796Sopenharmony_ci{ 232ba5c3796Sopenharmony_ci if (path.empty()) { 233ba5c3796Sopenharmony_ci return path; 234ba5c3796Sopenharmony_ci } 235ba5c3796Sopenharmony_ci return OHOS::IncludeTrailingPathDelimiter(path); 236ba5c3796Sopenharmony_ci} 237ba5c3796Sopenharmony_ci 238ba5c3796Sopenharmony_cistd::string KernelInterface::JoinPath(const std::string& prefixPath, const std::string& subPath) 239ba5c3796Sopenharmony_ci{ 240ba5c3796Sopenharmony_ci return AddDelimiter(prefixPath) + subPath; 241ba5c3796Sopenharmony_ci} 242ba5c3796Sopenharmony_ci 243ba5c3796Sopenharmony_cistd::string KernelInterface::JoinPath(const std::string& prefixPath, const std::string& midPath, 244ba5c3796Sopenharmony_ci const std::string& subPath) 245ba5c3796Sopenharmony_ci{ 246ba5c3796Sopenharmony_ci return JoinPath(JoinPath(prefixPath, midPath), subPath); 247ba5c3796Sopenharmony_ci} 248ba5c3796Sopenharmony_ci 249ba5c3796Sopenharmony_cibool KernelInterface::GetPidProcInfo(struct ProcInfo &procInfo) 250ba5c3796Sopenharmony_ci{ 251ba5c3796Sopenharmony_ci HILOGD("called!"); 252ba5c3796Sopenharmony_ci 253ba5c3796Sopenharmony_ci std::string statPath = JoinPath("/proc/", std::to_string(procInfo.pid), "/stat"); 254ba5c3796Sopenharmony_ci 255ba5c3796Sopenharmony_ci // format like: 256ba5c3796Sopenharmony_ci // 1 (init) S 0 0 0 0 -1 4210944 1 ... 257ba5c3796Sopenharmony_ci std::string stat; 258ba5c3796Sopenharmony_ci std::string statm; 259ba5c3796Sopenharmony_ci std::string statPid; 260ba5c3796Sopenharmony_ci std::string vss; 261ba5c3796Sopenharmony_ci std::string rss; 262ba5c3796Sopenharmony_ci if (!ReadFromFile(statPath, stat)) { 263ba5c3796Sopenharmony_ci HILOGD("stat file error!"); 264ba5c3796Sopenharmony_ci return false; 265ba5c3796Sopenharmony_ci } 266ba5c3796Sopenharmony_ci std::istringstream isStat(stat); 267ba5c3796Sopenharmony_ci isStat >> statPid >> procInfo.name >> procInfo.status; 268ba5c3796Sopenharmony_ci 269ba5c3796Sopenharmony_ci if (statPid != std::to_string(procInfo.pid)) { 270ba5c3796Sopenharmony_ci HILOGD("pid error!"); 271ba5c3796Sopenharmony_ci return false; 272ba5c3796Sopenharmony_ci } 273ba5c3796Sopenharmony_ci 274ba5c3796Sopenharmony_ci std::string statmPath = JoinPath("/proc/", std::to_string(procInfo.pid), "/statm"); 275ba5c3796Sopenharmony_ci // format like: 276ba5c3796Sopenharmony_ci // 640 472 369 38 0 115 0 277ba5c3796Sopenharmony_ci if (!ReadFromFile(statmPath, statm)) { 278ba5c3796Sopenharmony_ci HILOGD("statm file error!"); 279ba5c3796Sopenharmony_ci return false; 280ba5c3796Sopenharmony_ci } 281ba5c3796Sopenharmony_ci std::istringstream isStatm(statm); 282ba5c3796Sopenharmony_ci isStatm >> vss >> rss; // pages 283ba5c3796Sopenharmony_ci int rssValue = 0; 284ba5c3796Sopenharmony_ci try { 285ba5c3796Sopenharmony_ci rssValue = std::stoi(rss); 286ba5c3796Sopenharmony_ci } catch (...) { 287ba5c3796Sopenharmony_ci HILOGE("stoi(%{public}s) failed!", rss.c_str()); 288ba5c3796Sopenharmony_ci return false; 289ba5c3796Sopenharmony_ci } 290ba5c3796Sopenharmony_ci 291ba5c3796Sopenharmony_ci if (rssValue < 0 || rssValue > INT_MAX / PAGE_TO_KB) { 292ba5c3796Sopenharmony_ci HILOGE("rssValue=%{public}d, rss is less than 0 or overflow!", rssValue); 293ba5c3796Sopenharmony_ci return false; 294ba5c3796Sopenharmony_ci } 295ba5c3796Sopenharmony_ci procInfo.size = rssValue * PAGE_TO_KB; 296ba5c3796Sopenharmony_ci HILOGI("GetProcInfo success: name is %{public}s, status is %{public}s, size = %{public}d KB", 297ba5c3796Sopenharmony_ci procInfo.name.c_str(), procInfo.status.c_str(), procInfo.size); 298ba5c3796Sopenharmony_ci return true; 299ba5c3796Sopenharmony_ci} 300ba5c3796Sopenharmony_ci 301ba5c3796Sopenharmony_cibool KernelInterface::GetProcNameByPid(int pid, std::string &name) 302ba5c3796Sopenharmony_ci{ 303ba5c3796Sopenharmony_ci std::string statusPath = JoinPath("/proc/", std::to_string(pid), "/status"); 304ba5c3796Sopenharmony_ci std::string statusContent; 305ba5c3796Sopenharmony_ci std::string nameTag; 306ba5c3796Sopenharmony_ci if (!ReadFromFile(statusPath, statusContent)) { 307ba5c3796Sopenharmony_ci HILOGE("status file [%{public}s] error!", statusPath.c_str()); 308ba5c3796Sopenharmony_ci return false; 309ba5c3796Sopenharmony_ci } 310ba5c3796Sopenharmony_ci std::istringstream statusStream(statusContent); 311ba5c3796Sopenharmony_ci statusStream >> nameTag >> name; 312ba5c3796Sopenharmony_ci return true; 313ba5c3796Sopenharmony_ci} 314ba5c3796Sopenharmony_ci 315ba5c3796Sopenharmony_civoid KernelInterface::ReadZswapdPressureShow(std::map<std::string, std::string>& result) 316ba5c3796Sopenharmony_ci{ 317ba5c3796Sopenharmony_ci std::string contentStr; 318ba5c3796Sopenharmony_ci if (!ReadFromFile(ZWAPD_PRESSURE_SHOW_PATH, contentStr)) { 319ba5c3796Sopenharmony_ci HILOGE("read %{public}s faild, content=[%{public}s]", ZWAPD_PRESSURE_SHOW_PATH.c_str(), contentStr.c_str()); 320ba5c3796Sopenharmony_ci return; 321ba5c3796Sopenharmony_ci } 322ba5c3796Sopenharmony_ci char *contentPtr = new char[contentStr.size() + 1]; 323ba5c3796Sopenharmony_ci if (contentPtr == nullptr) { 324ba5c3796Sopenharmony_ci HILOGE("alloc buffer fail"); 325ba5c3796Sopenharmony_ci return; 326ba5c3796Sopenharmony_ci } 327ba5c3796Sopenharmony_ci if (strcpy_s(contentPtr, contentStr.size() + 1, contentStr.c_str()) != EOK) { 328ba5c3796Sopenharmony_ci HILOGE("copy fail"); 329ba5c3796Sopenharmony_ci delete [] contentPtr; 330ba5c3796Sopenharmony_ci return; 331ba5c3796Sopenharmony_ci } 332ba5c3796Sopenharmony_ci char *restPtr; 333ba5c3796Sopenharmony_ci char *line = strtok_r(contentPtr, "\n", &restPtr); 334ba5c3796Sopenharmony_ci do { 335ba5c3796Sopenharmony_ci for (size_t i = 0; i < strlen(line); i++) { 336ba5c3796Sopenharmony_ci if (line[i] == ':') { 337ba5c3796Sopenharmony_ci line[i] = ' '; 338ba5c3796Sopenharmony_ci } 339ba5c3796Sopenharmony_ci } 340ba5c3796Sopenharmony_ci std::string lineStr(line); 341ba5c3796Sopenharmony_ci std::istringstream is(lineStr); 342ba5c3796Sopenharmony_ci std::string name; 343ba5c3796Sopenharmony_ci std::string value; 344ba5c3796Sopenharmony_ci is >> name >> value; 345ba5c3796Sopenharmony_ci result.insert(std::make_pair(name, value)); 346ba5c3796Sopenharmony_ci 347ba5c3796Sopenharmony_ci line = strtok_r(NULL, "\n", &restPtr); 348ba5c3796Sopenharmony_ci } while (line); 349ba5c3796Sopenharmony_ci if (restPtr) { 350ba5c3796Sopenharmony_ci delete [] restPtr; 351ba5c3796Sopenharmony_ci } 352ba5c3796Sopenharmony_ci if (contentPtr) { 353ba5c3796Sopenharmony_ci delete [] contentPtr; 354ba5c3796Sopenharmony_ci } 355ba5c3796Sopenharmony_ci return; 356ba5c3796Sopenharmony_ci} 357ba5c3796Sopenharmony_ci 358ba5c3796Sopenharmony_ciint KernelInterface::GetCurrentBuffer() 359ba5c3796Sopenharmony_ci{ 360ba5c3796Sopenharmony_ci std::map<std::string, std::string> result; 361ba5c3796Sopenharmony_ci ReadZswapdPressureShow(result); 362ba5c3796Sopenharmony_ci auto value = result.find(ZWAPD_PRESSURE_SHOW_BUFFER_SIZE); 363ba5c3796Sopenharmony_ci if (value != result.end()) { 364ba5c3796Sopenharmony_ci#ifdef USE_HYPERHOLD_MEMORY 365ba5c3796Sopenharmony_ci HILOGD("buffer_size=%{public}s MB", result[ZWAPD_PRESSURE_SHOW_BUFFER_SIZE].c_str()); 366ba5c3796Sopenharmony_ci return atoi(result[ZWAPD_PRESSURE_SHOW_BUFFER_SIZE].c_str()) * KB_PER_MB; 367ba5c3796Sopenharmony_ci#else 368ba5c3796Sopenharmony_ci HILOGD("buffer_size=%{public}s KB", result[ZWAPD_PRESSURE_SHOW_BUFFER_SIZE].c_str()); 369ba5c3796Sopenharmony_ci return atoi(result[ZWAPD_PRESSURE_SHOW_BUFFER_SIZE].c_str()); 370ba5c3796Sopenharmony_ci#endif 371ba5c3796Sopenharmony_ci } 372ba5c3796Sopenharmony_ci return MAX_BUFFER_KB; 373ba5c3796Sopenharmony_ci} 374ba5c3796Sopenharmony_ci 375ba5c3796Sopenharmony_ciint KernelInterface::KillOneProcessByPid(int pid) 376ba5c3796Sopenharmony_ci{ 377ba5c3796Sopenharmony_ci HILOGD("called! pid=%{public}d", pid); 378ba5c3796Sopenharmony_ci struct ProcInfo procInfo; 379ba5c3796Sopenharmony_ci int freedBuffer = 0; 380ba5c3796Sopenharmony_ci procInfo.pid = pid; 381ba5c3796Sopenharmony_ci 382ba5c3796Sopenharmony_ci if (!GetPidProcInfo(procInfo)) { 383ba5c3796Sopenharmony_ci HILOGE("GetPidProcInfo fail !!!"); 384ba5c3796Sopenharmony_ci goto out; 385ba5c3796Sopenharmony_ci } 386ba5c3796Sopenharmony_ci 387ba5c3796Sopenharmony_ci if (procInfo.status == "D") { 388ba5c3796Sopenharmony_ci HILOGE("Task %{public}s is at D status!", procInfo.name.c_str()); 389ba5c3796Sopenharmony_ci goto out; 390ba5c3796Sopenharmony_ci } 391ba5c3796Sopenharmony_ci 392ba5c3796Sopenharmony_ci if (kill(pid, SIGKILL)) { 393ba5c3796Sopenharmony_ci HILOGE("Kill %{public}s errno=%{public}d!", procInfo.name.c_str(), errno); 394ba5c3796Sopenharmony_ci } 395ba5c3796Sopenharmony_ci HILOGE("%{public}s has been Killed ! (pid=%{public}d, freedSize=%{public}d KB)", 396ba5c3796Sopenharmony_ci procInfo.name.c_str(), procInfo.pid, procInfo.size); 397ba5c3796Sopenharmony_ci 398ba5c3796Sopenharmony_ci freedBuffer = procInfo.size; 399ba5c3796Sopenharmony_ciout: 400ba5c3796Sopenharmony_ci return freedBuffer; 401ba5c3796Sopenharmony_ci} 402ba5c3796Sopenharmony_ci 403ba5c3796Sopenharmony_cibool KernelInterface::GetAllProcPids(std::vector<unsigned int> &pids) 404ba5c3796Sopenharmony_ci{ 405ba5c3796Sopenharmony_ci pids.clear(); 406ba5c3796Sopenharmony_ci DIR *dir = opendir(ROOT_PROC_PATH.c_str()); 407ba5c3796Sopenharmony_ci if (dir == nullptr) { 408ba5c3796Sopenharmony_ci HILOGE("dir %{public}s is not exist", ROOT_PROC_PATH.c_str()); 409ba5c3796Sopenharmony_ci return false; 410ba5c3796Sopenharmony_ci } 411ba5c3796Sopenharmony_ci struct dirent *ptr = nullptr; 412ba5c3796Sopenharmony_ci while ((ptr = readdir(dir)) != nullptr) { 413ba5c3796Sopenharmony_ci if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) { 414ba5c3796Sopenharmony_ci // current dir OR parent dir 415ba5c3796Sopenharmony_ci continue; 416ba5c3796Sopenharmony_ci } else if (ptr->d_type == DT_DIR) { 417ba5c3796Sopenharmony_ci int pid = atoi(ptr->d_name); 418ba5c3796Sopenharmony_ci if (pid > 0) { 419ba5c3796Sopenharmony_ci pids.push_back((unsigned int)pid); 420ba5c3796Sopenharmony_ci } 421ba5c3796Sopenharmony_ci } 422ba5c3796Sopenharmony_ci } 423ba5c3796Sopenharmony_ci if (dir) { 424ba5c3796Sopenharmony_ci closedir(dir); 425ba5c3796Sopenharmony_ci } 426ba5c3796Sopenharmony_ci HILOGD("there are %{public}zu pids under %{public}s", pids.size(), ROOT_PROC_PATH.c_str()); 427ba5c3796Sopenharmony_ci return true; 428ba5c3796Sopenharmony_ci} 429ba5c3796Sopenharmony_ci 430ba5c3796Sopenharmony_cibool KernelInterface::GetUidByPid(unsigned int pid, unsigned int& uid) 431ba5c3796Sopenharmony_ci{ 432ba5c3796Sopenharmony_ci std::string path = JoinPath(ROOT_PROC_PATH, std::to_string(pid), "status"); 433ba5c3796Sopenharmony_ci std::string content; 434ba5c3796Sopenharmony_ci if (!ReadFromFile(path, content)) { 435ba5c3796Sopenharmony_ci HILOGE("read file failed. %{public}s", path.c_str()); 436ba5c3796Sopenharmony_ci return false; 437ba5c3796Sopenharmony_ci } 438ba5c3796Sopenharmony_ci content = std::regex_replace(content, std::regex("\n+"), " "); // replace \n with space 439ba5c3796Sopenharmony_ci std::regex re(".*Uid:[[:s:]]*([[:d:]]+)[[:s:]]*([[:d:]]+)[[:s:]]*([[:d:]]+)[[:s:]]*([[:d:]]+).*"); 440ba5c3796Sopenharmony_ci std::smatch res; 441ba5c3796Sopenharmony_ci if (!std::regex_match(content, res, re)) { 442ba5c3796Sopenharmony_ci HILOGD("re not match. %{public}s", content.c_str()); 443ba5c3796Sopenharmony_ci return false; 444ba5c3796Sopenharmony_ci } 445ba5c3796Sopenharmony_ci try { 446ba5c3796Sopenharmony_ci uid = (unsigned int)std::stoi(res.str(1)); // 1: Uid index 447ba5c3796Sopenharmony_ci } catch (...) { 448ba5c3796Sopenharmony_ci HILOGE("stoi(%{public}s) failed", res.str(1).c_str()); 449ba5c3796Sopenharmony_ci return false; 450ba5c3796Sopenharmony_ci } 451ba5c3796Sopenharmony_ci return true; 452ba5c3796Sopenharmony_ci} 453ba5c3796Sopenharmony_ci 454ba5c3796Sopenharmony_civoid DeleteCharArrayIfNotNull(char * charArray) 455ba5c3796Sopenharmony_ci{ 456ba5c3796Sopenharmony_ci if (charArray) { 457ba5c3796Sopenharmony_ci delete [] charArray; 458ba5c3796Sopenharmony_ci charArray = nullptr; 459ba5c3796Sopenharmony_ci } 460ba5c3796Sopenharmony_ci} 461ba5c3796Sopenharmony_ci 462ba5c3796Sopenharmony_cibool KernelInterface::ReadSwapOutKBSinceKernelBoot(const std::string &path, const std::string &tagStr, 463ba5c3796Sopenharmony_ci unsigned long long &ret) 464ba5c3796Sopenharmony_ci{ 465ba5c3796Sopenharmony_ci std::string contentStr; 466ba5c3796Sopenharmony_ci if (!ReadFromFile(path, contentStr)) { 467ba5c3796Sopenharmony_ci return false; 468ba5c3796Sopenharmony_ci } 469ba5c3796Sopenharmony_ci char *contentPtr = new char[contentStr.size() + 1]; 470ba5c3796Sopenharmony_ci if (contentPtr == nullptr) { 471ba5c3796Sopenharmony_ci HILOGE("alloc buffer fail"); 472ba5c3796Sopenharmony_ci return false; 473ba5c3796Sopenharmony_ci } 474ba5c3796Sopenharmony_ci if (strcpy_s(contentPtr, contentStr.size() + 1, contentStr.c_str()) != EOK) { 475ba5c3796Sopenharmony_ci HILOGE("copy fail"); 476ba5c3796Sopenharmony_ci DeleteCharArrayIfNotNull(contentPtr); 477ba5c3796Sopenharmony_ci return false; 478ba5c3796Sopenharmony_ci } 479ba5c3796Sopenharmony_ci bool success = false; 480ba5c3796Sopenharmony_ci char *restPtr; 481ba5c3796Sopenharmony_ci char *line = strtok_r(contentPtr, "\n", &restPtr); 482ba5c3796Sopenharmony_ci do { 483ba5c3796Sopenharmony_ci std::string lineStr(line); 484ba5c3796Sopenharmony_ci 485ba5c3796Sopenharmony_ci size_t i = 0; 486ba5c3796Sopenharmony_ci for (; i < strlen(line); i++) { 487ba5c3796Sopenharmony_ci if (line[i] == ':') { 488ba5c3796Sopenharmony_ci break; 489ba5c3796Sopenharmony_ci } 490ba5c3796Sopenharmony_ci } 491ba5c3796Sopenharmony_ci if (i >= strlen(line) - 2) { // 2: no : in the line or : is at end of line 492ba5c3796Sopenharmony_ci line = strtok_r(NULL, "\n", &restPtr); 493ba5c3796Sopenharmony_ci continue; 494ba5c3796Sopenharmony_ci } 495ba5c3796Sopenharmony_ci std::string tag = lineStr.substr(0, i); 496ba5c3796Sopenharmony_ci if (tag == tagStr) { 497ba5c3796Sopenharmony_ci std::string value = lineStr.substr(i + 1); 498ba5c3796Sopenharmony_ci std::istringstream iss(value); 499ba5c3796Sopenharmony_ci std::string sizeStr; 500ba5c3796Sopenharmony_ci std::string unitStr; 501ba5c3796Sopenharmony_ci iss >> sizeStr >> unitStr; 502ba5c3796Sopenharmony_ci try { 503ba5c3796Sopenharmony_ci ret = std::strtoull(sizeStr.c_str(), nullptr, 10); // 10:Decimal 504ba5c3796Sopenharmony_ci success = true; 505ba5c3796Sopenharmony_ci } catch (...) { 506ba5c3796Sopenharmony_ci HILOGE("parse [%{public}s] to unsigned long long error!", sizeStr.c_str()); 507ba5c3796Sopenharmony_ci } 508ba5c3796Sopenharmony_ci break; 509ba5c3796Sopenharmony_ci } 510ba5c3796Sopenharmony_ci 511ba5c3796Sopenharmony_ci line = strtok_r(NULL, "\n", &restPtr); 512ba5c3796Sopenharmony_ci } while (line); 513ba5c3796Sopenharmony_ci DeleteCharArrayIfNotNull(contentPtr); 514ba5c3796Sopenharmony_ci return success; 515ba5c3796Sopenharmony_ci} 516ba5c3796Sopenharmony_ci 517ba5c3796Sopenharmony_ciint KernelInterface::ParseMeminfo(const std::string &contentStr, const std::string &itemName) 518ba5c3796Sopenharmony_ci{ 519ba5c3796Sopenharmony_ci char *contentPtr = new (std::nothrow) char[contentStr.size() + 1]; 520ba5c3796Sopenharmony_ci if (contentPtr == nullptr) { 521ba5c3796Sopenharmony_ci HILOGE("alloc buffer fail"); 522ba5c3796Sopenharmony_ci return -1; 523ba5c3796Sopenharmony_ci } 524ba5c3796Sopenharmony_ci if (strcpy_s(contentPtr, contentStr.size() + 1, contentStr.c_str()) != EOK) { 525ba5c3796Sopenharmony_ci HILOGE("copy fail"); 526ba5c3796Sopenharmony_ci delete [] contentPtr; 527ba5c3796Sopenharmony_ci return -1; 528ba5c3796Sopenharmony_ci } 529ba5c3796Sopenharmony_ci char *restPtr = nullptr; 530ba5c3796Sopenharmony_ci char *line = strtok_r(contentPtr, "\n", &restPtr); 531ba5c3796Sopenharmony_ci std::string name; 532ba5c3796Sopenharmony_ci std::string value; 533ba5c3796Sopenharmony_ci bool findTotalMem = false; 534ba5c3796Sopenharmony_ci do { 535ba5c3796Sopenharmony_ci for (size_t i = 0; i < strlen(line); i++) { 536ba5c3796Sopenharmony_ci if (line[i] == ':') { 537ba5c3796Sopenharmony_ci line[i] = ' '; 538ba5c3796Sopenharmony_ci } 539ba5c3796Sopenharmony_ci } 540ba5c3796Sopenharmony_ci std::string lineStr(line); 541ba5c3796Sopenharmony_ci std::istringstream is(lineStr); 542ba5c3796Sopenharmony_ci 543ba5c3796Sopenharmony_ci is >> name >> value; 544ba5c3796Sopenharmony_ci if (name == itemName) { 545ba5c3796Sopenharmony_ci findTotalMem = true; 546ba5c3796Sopenharmony_ci break; 547ba5c3796Sopenharmony_ci } 548ba5c3796Sopenharmony_ci line = strtok_r(NULL, "\n", &restPtr); 549ba5c3796Sopenharmony_ci } while (line); 550ba5c3796Sopenharmony_ci if (contentPtr) { 551ba5c3796Sopenharmony_ci delete [] contentPtr; 552ba5c3796Sopenharmony_ci } 553ba5c3796Sopenharmony_ci 554ba5c3796Sopenharmony_ci if (findTotalMem == false) { 555ba5c3796Sopenharmony_ci return -1; 556ba5c3796Sopenharmony_ci } 557ba5c3796Sopenharmony_ci std::string valueTemp = ""; 558ba5c3796Sopenharmony_ci for (auto c : value) { 559ba5c3796Sopenharmony_ci if (c >= '0' && c <= '9') { 560ba5c3796Sopenharmony_ci valueTemp = valueTemp + c; 561ba5c3796Sopenharmony_ci } 562ba5c3796Sopenharmony_ci } 563ba5c3796Sopenharmony_ci return atoi(valueTemp.c_str()); 564ba5c3796Sopenharmony_ci} 565ba5c3796Sopenharmony_ci 566ba5c3796Sopenharmony_ciint KernelInterface::GetTotalBuffer() 567ba5c3796Sopenharmony_ci{ 568ba5c3796Sopenharmony_ci if (totalBuffer_ >= 0) { 569ba5c3796Sopenharmony_ci return totalBuffer_; 570ba5c3796Sopenharmony_ci } 571ba5c3796Sopenharmony_ci 572ba5c3796Sopenharmony_ci std::string contentStr; 573ba5c3796Sopenharmony_ci if (!ReadFromFile(MEMINFO_PATH, contentStr)) { 574ba5c3796Sopenharmony_ci HILOGE("read %{public}s faild, content=[%{public}s]", MEMINFO_PATH.c_str(), contentStr.c_str()); 575ba5c3796Sopenharmony_ci return -1; 576ba5c3796Sopenharmony_ci } 577ba5c3796Sopenharmony_ci totalBuffer_ = ParseMeminfo(contentStr, TOTAL_MEMORY); 578ba5c3796Sopenharmony_ci return totalBuffer_; 579ba5c3796Sopenharmony_ci} 580ba5c3796Sopenharmony_ci 581ba5c3796Sopenharmony_cibool KernelInterface::GetMemcgPids(const std::string &memcgPath, std::vector<int> &memcgPids) 582ba5c3796Sopenharmony_ci{ 583ba5c3796Sopenharmony_ci std::string path = JoinPath(memcgPath, FILE_MEMCG_PROCS); 584ba5c3796Sopenharmony_ci std::vector<std::string> strLines; 585ba5c3796Sopenharmony_ci if (!ReadLinesFromFile(path, strLines)) { 586ba5c3796Sopenharmony_ci HILOGE("read file and split to lines failed : %{public}s", path.c_str()); 587ba5c3796Sopenharmony_ci return false; 588ba5c3796Sopenharmony_ci } 589ba5c3796Sopenharmony_ci 590ba5c3796Sopenharmony_ci memcgPids.clear(); 591ba5c3796Sopenharmony_ci int pid; 592ba5c3796Sopenharmony_ci for (auto &it : strLines) { 593ba5c3796Sopenharmony_ci try { 594ba5c3796Sopenharmony_ci pid = stoi(it); 595ba5c3796Sopenharmony_ci } catch (...) { 596ba5c3796Sopenharmony_ci continue; 597ba5c3796Sopenharmony_ci } 598ba5c3796Sopenharmony_ci memcgPids.emplace_back(pid); 599ba5c3796Sopenharmony_ci } 600ba5c3796Sopenharmony_ci HILOGD("there are %{public}zu pids in %{public}s", memcgPids.size(), path.c_str()); 601ba5c3796Sopenharmony_ci return true; 602ba5c3796Sopenharmony_ci} 603ba5c3796Sopenharmony_ci 604ba5c3796Sopenharmony_cibool KernelInterface::GetAllUserIds(std::vector<int> &userIds) 605ba5c3796Sopenharmony_ci{ 606ba5c3796Sopenharmony_ci userIds.clear(); 607ba5c3796Sopenharmony_ci DIR *dir = opendir(MEMCG_BASE_PATH.c_str()); 608ba5c3796Sopenharmony_ci if (dir == nullptr) { 609ba5c3796Sopenharmony_ci HILOGE("dir %{public}s is not exist", MEMCG_BASE_PATH.c_str()); 610ba5c3796Sopenharmony_ci return false; 611ba5c3796Sopenharmony_ci } 612ba5c3796Sopenharmony_ci struct dirent *ptr = nullptr; 613ba5c3796Sopenharmony_ci while ((ptr = readdir(dir)) != nullptr) { 614ba5c3796Sopenharmony_ci if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) { 615ba5c3796Sopenharmony_ci // current dir OR parent dir 616ba5c3796Sopenharmony_ci continue; 617ba5c3796Sopenharmony_ci } else if (ptr->d_type == DT_DIR) { 618ba5c3796Sopenharmony_ci int userId = atoi(ptr->d_name); 619ba5c3796Sopenharmony_ci if (userId > 0) { 620ba5c3796Sopenharmony_ci userIds.push_back(userId); 621ba5c3796Sopenharmony_ci } 622ba5c3796Sopenharmony_ci } 623ba5c3796Sopenharmony_ci } 624ba5c3796Sopenharmony_ci if (dir) { 625ba5c3796Sopenharmony_ci closedir(dir); 626ba5c3796Sopenharmony_ci } 627ba5c3796Sopenharmony_ci HILOGD("there are %{public}zu userIds under %{public}s", userIds.size(), MEMCG_BASE_PATH.c_str()); 628ba5c3796Sopenharmony_ci return true; 629ba5c3796Sopenharmony_ci} 630ba5c3796Sopenharmony_ci 631ba5c3796Sopenharmony_civoid KernelInterface::SplitOneLineByDelim(const std::string &input, const char delimiter, 632ba5c3796Sopenharmony_ci std::vector<std::string> &res) 633ba5c3796Sopenharmony_ci{ 634ba5c3796Sopenharmony_ci std::stringstream ss(input); 635ba5c3796Sopenharmony_ci std::string temp; 636ba5c3796Sopenharmony_ci while (getline(ss, temp, delimiter)) { 637ba5c3796Sopenharmony_ci if (!temp.empty()) { 638ba5c3796Sopenharmony_ci res.emplace_back(temp); 639ba5c3796Sopenharmony_ci } 640ba5c3796Sopenharmony_ci } 641ba5c3796Sopenharmony_ci} 642ba5c3796Sopenharmony_ci 643ba5c3796Sopenharmony_civoid KernelInterface::SplitOneLineByBlank(const std::string &input, std::vector<std::string> &res) 644ba5c3796Sopenharmony_ci{ 645ba5c3796Sopenharmony_ci std::stringstream ss(input); 646ba5c3796Sopenharmony_ci std::string temp; 647ba5c3796Sopenharmony_ci while (ss >> temp) { 648ba5c3796Sopenharmony_ci if (!temp.empty()) { 649ba5c3796Sopenharmony_ci res.emplace_back(temp); 650ba5c3796Sopenharmony_ci } 651ba5c3796Sopenharmony_ci } 652ba5c3796Sopenharmony_ci} 653ba5c3796Sopenharmony_ci} // namespace Memory 654ba5c3796Sopenharmony_ci} // namespace OHOS 655