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