目录
0. 前言
Android中 logd 详解_私房菜的博客-CSDN博客_logd
里面讲了Java层Logd的框架和代码和Native的一些代码
1. Native的Log写过程解析
普通LogI会调用到ALOG -->位于logger_write.cpp
__android_log_print --> __android_log_logd_logger --> write_to_log
调用__android_log_logd_logger:
void __android_log_logd_logger(const struct __android_log_message* log_message) {
int buffer_id = log_message->buffer_id == LOG_ID_DEFAULT ? LOG_ID_MAIN : log_message->buffer_id;
struct iovec vec[3];
vec[0].iov_base =
const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(&log_message->priority));
vec[0].iov_len = 1;
vec[1].iov_base = const_cast<void*>(static_cast<const void*>(log_message->tag));
vec[1].iov_len = strlen(log_message->tag) + 1;
vec[2].iov_base = const_cast<void*>(static_cast<const void*>(log_message->message));
vec[2].iov_len = strlen(log_message->message) + 1;
write_to_log(static_cast<log_id_t>(buffer_id), vec, 3);
}
调用write_to_log做了一些参数检查,最终又调到了LogdWrite
static int write_to_log(log_id_t log_id, struct iovec* vec, size_t nr) {
int ret;
struct timespec ts;
...
clock_gettime(CLOCK_REALTIME, &ts);
if (log_id == LOG_ID_SECURITY)
if (vec[0].iov_len < 4)
ret = check_log_uid_permissions();
if (!__android_log_security())
if (logger_ratelimit(log_id, ts) == LOGGER_RATELIMIT_SHIELD)
...
ret = LogdWrite(log_id, &ts, vec, nr);
PmsgWrite(log_id, &ts, vec, nr);
return ret;
}
LogdWrite是往logd的socket中/dev/socket/logdw 这节点中写
int LogdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
LogdSocket& logd_socket = logId == LOG_ID_SECURITY ? LogdSocket::BlockingSocket() : LogdSocket::NonBlockingSocket();
if (__android_log_is_loggable_len(ANDROID_LOG_INFO, "liblog", strlen("liblog"))) {
ret = TEMP_FAILURE_RETRY(writev(logd_socket.sock(), newVec, 2));
if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
if (WriteDropLog(newVec, 2) != static_cast<int>(iov_length(newVec, 2)))
atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
}
}
if (RedirectLogWrite(logId)) {
ret = WriteAppLog(logId, newVec, i);
}
ret = TEMP_FAILURE_RETRY(writev(logd_socket.sock(), newVec, i));
if (ret < 0 && errno != EAGAIN) {
logd_socket.Reconnect();
ret = TEMP_FAILURE_RETRY(writev(logd_socket.sock(), newVec, i));
}
}
PmsgWrite
是往/dev/pmsg0节点中写, 这个节点是pstore 内核日志的通路
2. Socket的另一端Logd
system\logging\logd\main.cpp中规定了logd初始化的组件
SerializedLogBuffer TODO后面看看 socket on Android
LogListener->StartListener
int LogListener::GetLogSocket() {
static const char socketName[] = "logdw";
int sock = android_get_control_socket(socketName);
if (sock < 0) { // logd started up in init.sh
sock = socket_local_server(
socketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_DGRAM);
int on = 1;
if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
return -1;
}
}
return sock;
}
LogListener开始监听
void LogListener::HandleData() {
// + 1 to ensure null terminator if MAX_PAYLOAD buffer is received
__attribute__((uninitialized)) char
buffer[sizeof(android_log_header_t) + LOGGER_ENTRY_MAX_PAYLOAD + 1];
struct iovec iov = {buffer, sizeof(buffer) - 1};
alignas(4) char control[CMSG_SPACE(sizeof(struct ucred))];
struct msghdr hdr = {
nullptr, 0, &iov, 1, control, sizeof(control), 0,
};
// To clear the entire buffer is secure/safe, but this contributes to 1.68%
// overhead under logging load. We are safe because we check counts, but
// still need to clear null terminator
// memset(buffer, 0, sizeof(buffer));
ssize_t n = recvmsg(socket_, &hdr, 0);
...
logbuf_->Log(logId, header->realtime, cred->uid, cred->pid, header->tid, msg,
((size_t)n <= UINT16_MAX) ? (uint16_t)n : UINT16_MAX, secontext, secontext_len);
}
logbuf->log是刷写log的函数。
LogBuffer这个类可以研究一下,log的循环使用是怎么实现的?
3、Logcat
#system/core/logcat/logcat.cpp
main函数中直接调用logcat run,最终调用到函数
android_logger_list_read(logger_list.get(), &log_msg)
也是通过socket(logdr)来传递信息的