1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "log_kmsg.h" 17 #include <cstdlib> 18 #include <cinttypes> 19 #include <iostream> 20 #include <string> 21 #include <thread> 22 #include <fstream> 23 #include <sys/klog.h> 24 #include <sys/syslog.h> 25 #include <unistd.h> 26 #include <fcntl.h> 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <sys/prctl.h> 30 #include <init_file.h> 31 #include <hilog/log.h> 32 #include <log_utils.h> 33 34 namespace OHOS { 35 namespace HiviewDFX { 36 using namespace std; 37 GetInstance(HilogBuffer & hilogBuffer)38LogKmsg& LogKmsg::GetInstance(HilogBuffer& hilogBuffer) 39 { 40 static LogKmsg logKmsg(hilogBuffer); 41 return logKmsg; 42 } 43 LinuxReadOneKmsg(KmsgParser & parser)44ssize_t LogKmsg::LinuxReadOneKmsg(KmsgParser& parser) 45 { 46 std::vector<char> kmsgBuffer(BUFSIZ, '\0'); 47 ssize_t size = -1; 48 do { 49 size = read(kmsgCtl, kmsgBuffer.data(), BUFSIZ - 1); 50 } while (size < 0 && errno == EPIPE); 51 if (size > 0) { 52 std::optional<HilogMsgWrapper> msgWrap = parser.ParseKmsg(kmsgBuffer); 53 if (msgWrap.has_value()) { 54 size_t result = hilogBuffer.Insert(msgWrap->GetHilogMsg()); 55 if (result <= 0) { 56 return result; 57 } 58 } 59 } 60 return size; 61 } 62 LinuxReadAllKmsg()63int LogKmsg::LinuxReadAllKmsg() 64 { 65 ssize_t rdFailTimes = 0; 66 const ssize_t maxFailTime = 10; 67 kmsgCtl = GetControlFile("/dev/kmsg"); 68 if (kmsgCtl < 0) { 69 std::cout << "Cannot open kmsg! "; 70 PrintErrorno(errno); 71 return -1; 72 } 73 std::unique_ptr<KmsgParser> parser = std::make_unique<KmsgParser>(); 74 if (parser == nullptr) { 75 return -1; 76 } 77 while (true) { 78 if (threadStatus == STOP) { 79 break; 80 } 81 ssize_t sz = LinuxReadOneKmsg(*parser); 82 if (sz < 0) { 83 rdFailTimes++; 84 if (maxFailTime < rdFailTimes) { 85 std::cout << "Read kmsg failed more than maxFailTime" << std::endl; 86 return -1; 87 } 88 sleep(1); 89 continue; 90 } 91 rdFailTimes = 0; 92 } 93 return 1; 94 } 95 ReadAllKmsg()96void LogKmsg::ReadAllKmsg() 97 { 98 prctl(PR_SET_NAME, "hilogd.rd_kmsg"); 99 #ifdef __linux__ 100 std::cout << "Platform: Linux" << std::endl; 101 LinuxReadAllKmsg(); 102 #endif 103 } 104 Start()105void LogKmsg::Start() 106 { 107 std::lock_guard<decltype(startMtx)> lock(startMtx); 108 if (threadStatus == NONEXIST || threadStatus == STOP) { 109 logKmsgThread = std::thread ([this]() { 110 ReadAllKmsg(); 111 }); 112 } else { 113 std::cout << " Thread already started!\n"; 114 } 115 threadStatus = START; 116 } 117 Stop()118void LogKmsg::Stop() 119 { 120 if (threadStatus == NONEXIST || threadStatus == STOP) { 121 std::cout << "Thread was exited or not started!\n"; 122 return; 123 } 124 threadStatus = STOP; 125 if (logKmsgThread.joinable()) { 126 logKmsgThread.join(); 127 } 128 } 129 ~LogKmsg()130LogKmsg::~LogKmsg() 131 { 132 close(kmsgCtl); 133 } 134 } // namespace HiviewDFX 135 } // namespace OHOS 136