0、相关文件目录1、ALOGD写log流程
1.1 ALOGD打印log,传入可变参数1.2 logdw socket写log1.3 pmsg写入 /dev/pmsg0 2、logcat读取流程
2.1 logcat调用liblog流程2.2 logformat_ 申请和释放2.3 logger_list申请和释放2.4 android_logger_open打开设备log2.5 android_logger_list_read获取buffer2.6 android_log_printLogLine写log文件 3、logd流程
3.1 logd进程启动3.2 logd-reinit进程和 re-init线程3.3 LogListener监测socket logdw3.4 LogReader监测socket logdr3.5 logBuffer流程3.6 socket logd 交互3.7 kernel log流程3.8 selinux log流程3.9 logd各线程整理 4、整体流程图 0、相关文件目录
### liblog write//log_main logger_write定义log宏,组装可变内容write_to_logsystemcoreliblogincludeloglog_main.hsystemcorelibloglogger_write.cpp//写内容到pmsg /dev/pmsg0systemcoreliblogpmsg_writer.cpp//写内容到logdw /dev/socket/logdwsystemcorelibloglogd_writer.cpp### logcat readsystemcorelibloglogger_read.cppsystemcorelogcatlogcat.cppsystemcorelibloglogd_reader.cpp### logdsystemcorelogdmain.cpp//LogListener监听socket logdw把log写到logBuffersystemcorelogdLogListener.hsystemcorelogdLogListener.cpp//SocketListener socket的监听类systemcorelibsysutilssrcSocketListener.cppsystemcorelibsysutilsincludesysutilsSocketListener.h//记录每个使用LOG的pid客户端systemcorelibsysutilssrcSocketClient.cppsystemcorelogdFlushCommand.cpp//LogBuffer类systemcorelogdLogBuffer.cpp//LogReader监听logdr类systemcorelogdLogReader.cpp
1、ALOGD写log流程 1.1 ALOGD打印log,传入可变参数@systemcoreliblogincludeloglog_main.h
//ALOGD调用到ALOG#ifndef ALOGD#define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__))#endif//最终使用到android_printLog#ifndef LOG_PRI#define LOG_PRI(priority, tag, ...) android_printLog(priority, tag, __VA_ARGS__)#endif#define android_printLog(prio, tag, ...) __android_log_print(prio, tag, __VA_ARGS__)
__android_log_print把log内容拼装到__android_log_message,然后调用写
@systemcorelibloglogger_write.cppint __android_log_print(int prio, const char* tag, const char* fmt, ...) { ErrnoRestorer errno_restorer; if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) { return -EPERM; } //可变参数 va_list ap; char buf[LOG_BUF_SIZE]; va_start(ap, fmt); vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); va_end(ap); //拼凑log_message,然后写 __android_log_message log_message = { sizeof(__android_log_message), LOG_ID_MAIN, prio, tag, nullptr, 0, buf}; __android_log_write_log_message(&log_message); return 1;}void __android_log_write_log_message(__android_log_message* log_message) { ErrnoRestorer errno_restorer; //过滤buffer id if (log_message->buffer_id != LOG_ID_DEFAULT && log_message->buffer_id != LOG_ID_MAIN && log_message->buffer_id != LOG_ID_SYSTEM && log_message->buffer_id != LOG_ID_RADIO && log_message->buffer_id != LOG_ID_CRASH) { return; } //设置tag if (log_message->tag == nullptr) { log_message->tag = GetDefaultTag().c_str(); }//如果是fatal,abort_message#if __BIONIC__ if (log_message->priority == ANDROID_LOG_FATAL) { android_set_abort_message(log_message->message); }#endif //调用logger_function透传message logger_function(log_message);}//logger_function是函数__android_log_logd_logger#ifdef __ANDROID__static __android_logger_function logger_function = __android_log_logd_logger;#elsestatic __android_logger_function logger_function = __android_log_stderr_logger;#endif//__android_log_logd_logger继续转message到数组,最后write_to_logvoid __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;//io vector: iovec io数组申请3个,分别设置优先级,tag,message struct iovec vec[3]; vec[0].iov_base = const_cast
__android_log_message定义入下
//message包含 struct_size大小sizeof(__android_log_message)//buffer_id:这里是LOG_ID_MAIN,表示使用main log//priority:enum android_LogPriority 优先级越高,值越大//tag :设置的log tag//file:文件名不知道干啥 alogd是nullptr空//line;这里是0//message: message buf,这里是可变参数的内容struct __android_log_message { size_t struct_size; int32_t buffer_id; int32_t priority; const char* tag; const char* file; uint32_t line; const char* message; };
static int write_to_log(log_id_t log_id, struct iovec* vec, size_t nr) { int ret; struct timespec ts; if (log_id == LOG_ID_KERNEL) { return -EINVAL; //invalid无效错误 } //获取时间 clock_gettime(android_log_clockid(), &ts); //安全需要检测长度,权限,安全等等,ALOGD不是此id if (log_id == LOG_ID_SECURITY) { if (vec[0].iov_len < 4) { return -EINVAL; } ret = check_log_uid_permissions(); if (ret < 0) { return ret; } if (!__android_log_security()) { return -EPERM; } } else if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS) { if (vec[0].iov_len < 4) { return -EINVAL; } } ret = LogdWrite(log_id, &ts, vec, nr); PmsgWrite(log_id, &ts, vec, nr); return ret;}
1.2 logdw socket写log//这里就是每个客户端写的socket logdw
@systemcorelibloglogd_writer.cppstatic void LogdConnect() { sockaddr_un un = {}; un.sun_family = AF_UNIX; strcpy(un.sun_path, "/dev/socket/logdw"); TEMP_FAILURE_RETRY(connect(logd_socket, reinterpret_cast
LogdWrite函数把tid 时间 vec组装成新的newvec,通过writev写到socket logdw
int LogdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) { ssize_t ret; static const unsigned headerLength = 1; struct iovec newVec[nr + headerLength]; android_log_header_t header; size_t i, payloadSize; static atomic_int dropped; static atomic_int droppedSecurity; //获取 socket logdw GetSocket();//获取失败返回 if (logd_socket <= 0) { return -EBADF; }//logd本身不能用 if (getuid() == AID_LOGD) { return 0; } //log头包含id tid 和时间 header.tid = gettid(); header.realtime.tv_sec = ts->tv_sec; header.realtime.tv_nsec = ts->tv_nsec; //把header放入io数组 newVec[0].iov_base = (unsigned char*)&header; newVec[0].iov_len = sizeof(header); //LOG_ID_SECURITY int32_t snapshot = atomic_exchange_explicit(&droppedSecurity, 0, memory_order_relaxed); if (snapshot) { android_log_event_int_t buffer;... //writev是循环写数组内容到fd,这里是把数组写到socket里面logd_socket // The write below could be lost, but will never block. // EAGAIN occurs if logd is overloaded, other errors indicate that something went wrong with // the connection, so we reset it and try again. ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, i));//TEMP_FAILURE_RETRY定义writev函数while一直写 if (ret < 0 && errno != EAGAIN) { LogdConnect(); //如果失败是AGAIN,会重连socket在试一次 ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, i)); } if (ret < 0) { ret = -errno; } if (ret > (ssize_t)sizeof(header)) { ret -= sizeof(header); } else if (ret < 0) { atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed); if (logId == LOG_ID_SECURITY) { atomic_fetch_add_explicit(&droppedSecurity, 1, memory_order_relaxed); } } return ret;}
1.3 pmsg写入 /dev/pmsg0log内容,分别写入socket logdw和pmsg /dev/pmsg0文件
@androidsystemcoreliblogpmsg_writer.cppstatic void GetPmsgFd() { if (pmsg_fd != 0) { return; } int new_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRonLY | O_CLOEXEC)); if (new_fd <= 0) { return; } int uninitialized_value = 0; if (!pmsg_fd.compare_exchange_strong(uninitialized_value, new_fd)) { close(new_fd); return; }}void PmsgClose() { if (pmsg_fd > 0) { close(pmsg_fd); } pmsg_fd = 0;}int PmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) { static const unsigned headerLength = 2; struct iovec newVec[nr + headerLength]; android_log_header_t header; android_pmsg_log_header_t pmsgHeader; size_t i, payloadSize; ssize_t ret;//userdebug就不走 if (!__android_log_is_debuggable()) { if (logId != LOG_ID_EVENTS && logId != LOG_ID_SECURITY) { return -1; } if (logId == LOG_ID_EVENTS) { if (vec[0].iov_len < 4) { return -EINVAL; } if (SNET_EVENT_LOG_TAG != *static_cast
logcat客户端精简流程入下
@logcat.cppint Logcat::Run() { //reset文件fd output_fd_.reset(); //设置格式threadtime SetLogFormat("threadtime"); int mode = ANDROID_LOG_RDONLY; size_t tail_lines = 0; size_t pid = 0; unsigned id_mask = -1; //int err = android_log_addFilterString(logformat_.get(), env_tags_orig); //logger_list初始化 std::unique_ptr
void Logcat::ProcessBuffer(struct log_msg* buf) { int bytesWritten = 0; int err; AndroidLogEntry entry; char binaryMsgBuf[1024]; bool is_binary = buf->id() == LOG_ID_EVENTS || buf->id() == LOG_ID_STATS || buf->id() == LOG_ID_SECURITY; if (is_binary) { if (!event_tag_map_ && !has_opened_event_tag_map_) { event_tag_map_.reset(android_openEventTagMap(nullptr)); has_opened_event_tag_map_ = true; } err = android_log_processBinaryLogBuffer(&buf->entry, &entry, event_tag_map_.get(), binaryMsgBuf, sizeof(binaryMsgBuf)); // printf(">>> pri=%d len=%d msg='%s'n", // entry.priority, entry.messageLen, entry.message); } else { //处理buffer err = android_log_processLogBuffer(&buf->entry, &entry); } if (err < 0) return; //打印分界线内容 -----main格式 PrintDividers(buf->id(), false); //是否需要打印 if (android_log_shouldPrintLine(logformat_.get(), std::string(entry.tag, entry.tagLen).c_str(), entry.priority)) { //android_log_printLogLine写buffer内容到fd,如果是fd是终端就打印到终端 bytesWritten = android_log_printLogLine(logformat_.get(), output_fd_.get(), &entry); if (bytesWritten < 0) { ALOGE("bytesWritten < 0"); error(EXIT_FAILURE, 0, "Output error."); } } //已经写的内容大小 out_byte_count_ += bytesWritten; //大小超过限额就需要把log存到另外文件 if (log_rotate_size_kb_ > 0 && (out_byte_count_ / 1024) >= log_rotate_size_kb_) { ALOGE("RotateLogs < 0"); RotateLogs(); }}
LOGCAT客户端的流程大概入下
1、logcat先解析参数可以使用logcat --help查看2、初始化资源包括output_fd, logger_list3、android_logger_open打开各个logid4、android_logger_list_read读取log到log_msg5、android_log_printLogLine打印log
2.2 logformat_ 申请和释放AndroidLogFormat_t和AndroidLogPrintFormat定义
struct AndroidLogFormat_t { android_LogPriority global_pri; FilterInfo* filters; AndroidLogPrintFormat format; bool colored_output; bool usec_time_output; bool nsec_time_output; bool printable_output; bool year_output; bool zone_output; bool epoch_output; bool monotonic_output; bool uid_output; bool descriptive_output;};typedef enum { FORMAT_OFF = 0, FORMAT_BRIEF, FORMAT_PROCESS, FORMAT_TAG, FORMAT_THREAD, FORMAT_RAW, FORMAT_TIME, FORMAT_THREADTIME, FORMAT_LONG, FORMAT_MODIFIER_COLOR, FORMAT_MODIFIER_TIME_USEC, FORMAT_MODIFIER_PRINTABLE, FORMAT_MODIFIER_YEAR, FORMAT_MODIFIER_ZONE, FORMAT_MODIFIER_EPOCH, FORMAT_MODIFIER_MONOTONIC, FORMAT_MODIFIER_UID, FORMAT_MODIFIER_DEscript, FORMAT_MODIFIER_TIME_NSEC, } AndroidLogPrintFormat;
@logcat.hpp // Used for all options android::base::unique_fd output_fd_{dup(STDOUT_FILENO)}; std::unique_ptr logformat_{ android_log_format_new(), &android_log_format_free};
log格式包含优先级,输出,过滤器等
AndroidLogFormat* android_log_format_new() { AndroidLogFormat* p_ret; p_ret = static_cast(calloc(1, sizeof(AndroidLogFormat))); p_ret->global_pri = ANDROID_LOG_VERBOSE; p_ret->format = FORMAT_BRIEF; p_ret->colored_output = false; p_ret->usec_time_output = false; p_ret->nsec_time_output = false; p_ret->printable_output = false; p_ret->year_output = false; p_ret->zone_output = false; p_ret->epoch_output = false;#ifdef __ANDROID__ p_ret->monotonic_output = android_log_clockid() == CLOCK_MONOTONIC;#else p_ret->monotonic_output = false;#endif p_ret->uid_output = false; p_ret->descriptive_output = false; descriptive_output = false; return p_ret;}
释放AndroidLogFormat,里面包含filter过滤
void android_log_format_free(AndroidLogFormat* p_format) { FilterInfo *p_info, *p_info_old; p_info = p_format->filters; while (p_info != NULL) { p_info_old = p_info; p_info = p_info->p_next; free(p_info_old); } free(p_format); while (!list_empty(&convertHead)) { struct listnode* node = list_head(&convertHead); list_remove(node); LOG_ALWAYS_FATAL_IF(node == list_head(&convertHead), "corrupted list"); free(node); }}
logcat设置格式
@logcat.cppint Logcat::SetLogFormat(const char* format_string) { //字符串转 AndroidLogPrintFormat format = android_log_formatFromString(format_string); // invalid string? if (format == FORMAT_OFF) return -1; //设置格式 return android_log_setPrintFormat(logformat_.get(), format);}
直接设置format threadtime
SetLogFormat(“threadtime”)
int android_log_setPrintFormat(AndroidLogFormat* p_format, AndroidLogPrintFormat format) { switch (format) {... } p_format->format = format; return 1;}
2.3 logger_list申请和释放logcat申请logger_list android_logger_list_alloc,自动释放 android_logger_list_free
@logcat.cppstd::unique_ptr
logger_list定义
@systemcorelibloglogger.hstruct logger_list { atomic_int fd;//原子操作int,多线程不用锁确保安全 int mode;//mode unsigned int tail;//尾巴 log_time start;//time pid_t pid;//pid uint32_t log_mask;//mask};
@systemcorelibloglogger_read.cppstruct logger_list* android_logger_list_alloc(int mode, unsigned int tail, pid_t pid) { return android_logger_list_alloc_internal(mode, tail, log_time(0, 0), pid);}static struct logger_list* android_logger_list_alloc_internal(int mode, unsigned int tail, log_time start, pid_t pid) { //calloc申请一个logger_list auto* logger_list = static_cast
@logcat.cpp for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) { if (!(id_mask & (1 << i))) continue; const char* buffer_name = android_log_id_to_name(static_cast
android_logger_open 把需要打印的logid添加进list,同时返回logger是使用logd还是pmsg
struct logger* android_logger_open(struct logger_list* logger_list, log_id_t logId) { if (!logger_list || (logId >= LOG_ID_MAX)) { return nullptr; } logger_list->log_mask |= 1 << logId; //把打开的logID添加进logger_list,mask就可以打开多个log uintptr_t logger = logId; //logger 正常不是pstore mode时,值是LOGGER_LOGD logger |= (logger_list->mode & ANDROID_LOG_PSTORE) ? LOGGER_PMSG : LOGGER_LOGD; return reinterpret_cast
struct log_msg定义,包含buffer, entry
@systemcoreliblogincludeloglog_read.hstruct log_msg { union { unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1]; struct logger_entry entry; } __attribute__((aligned(4)));#ifdef __cplusplus bool operator==(const log_msg& T) const { return (entry.sec == T.entry.sec) && (entry.nsec == T.entry.nsec); } bool operator!=(const log_msg& T) const { return !(*this == T); } bool operator<(const log_msg& T) const { return (entry.sec < T.entry.sec) || ((entry.sec == T.entry.sec) && (entry.nsec < T.entry.nsec)); } bool operator>=(const log_msg& T) const { return !(*this < T); } bool operator>(const log_msg& T) const { return (entry.sec > T.entry.sec) || ((entry.sec == T.entry.sec) && (entry.nsec > T.entry.nsec)); } bool operator<=(const log_msg& T) const { return !(*this > T); } uint64_t nsec() const { return static_cast
entry包含长度size,uid pid tid等.
每一个entry都包含pid tid等,就可以用这个来过滤当前buffer了
struct logger_entry { uint16_t len; uint16_t hdr_size; int32_t pid; uint32_t tid; uint32_t sec; uint32_t nsec; uint32_t lid; uint32_t uid; };
@logger_read.cpp//读取log到log_msg,logger_list包含需要读取的logidint android_logger_list_read(struct logger_list* logger_list, struct log_msg* log_msg) { if (logger_list == nullptr || logger_list->log_mask == 0) { return -EINVAL; } int ret = 0;//这里使用LogdRead#ifdef __ANDROID__ if (logger_list->mode & ANDROID_LOG_PSTORE) { ret = PmsgRead(logger_list, log_msg); } else { ret = LogdRead(logger_list, log_msg); }#endif if (ret <= 0) { return ret; }//检测ret结果省略...//末尾设置 log_msg->buf[log_msg->entry.len + log_msg->entry.hdr_size] = ''; return ret;}
@logd_reader.cppint LogdRead(struct logger_list* logger_list, struct log_msg* log_msg) {//open会让打开的/dev/socket/loddr赋值给logger_list,然后write socket int ret = logdOpen(logger_list); if (ret < 0) { return ret; }//recv读取socket logdr的内容到log_msg里面 ret = TEMP_FAILURE_RETRY(recv(ret, log_msg, LOGGER_ENTRY_MAX_LEN, 0)); if ((logger_list->mode & ANDROID_LOG_NONBLOCK) && ret == 0) { return -EAGAIN;//判断返回值 } if (ret == -1) { return -errno; } return ret;}static int logdOpen(struct logger_list* logger_list) { char buffer[256], *cp, c; int ret, remaining, sock; //查看fd > 0,证明已经打开过socket,就return sock = atomic_load(&logger_list->fd); if (sock > 0) { return sock; } //连接/dev/socket/logdr,把fd给sock sock = socket_local_client("logdr", SOCK_SEQPACKET); if (sock <= 0) { if ((sock == -1) && errno) { return -errno; } return sock; } strcpy(buffer, (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose" : "stream"); cp = buffer + strlen(buffer); strcpy(cp, " lids"); cp += 5; c = '='; remaining = sizeof(buffer) - (cp - buffer); for (size_t log_id = 0; log_id < LOG_ID_MAX; ++log_id) { if ((1 << log_id) & logger_list->log_mask) { ret = snprintf(cp, remaining, "%c%zu", c, log_id); ret = MIN(ret, remaining); remaining -= ret; cp += ret; c = ','; } } if (logger_list->tail) { ret = snprintf(cp, remaining, " tail=%u", logger_list->tail); ret = MIN(ret, remaining); remaining -= ret; cp += ret; } if (logger_list->start.tv_sec || logger_list->start.tv_nsec) { if (logger_list->mode & ANDROID_LOG_WRAP) { // ToDo: alternate API to allow timeout to be adjusted. ret = snprintf(cp, remaining, " timeout=%u", ANDROID_LOG_WRAP_DEFAULT_TIMEOUT); ret = MIN(ret, remaining); remaining -= ret; cp += ret; } ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32, logger_list->start.tv_sec, logger_list->start.tv_nsec); ret = MIN(ret, remaining); remaining -= ret; cp += ret; } if (logger_list->pid) { ret = snprintf(cp, remaining, " pid=%u", logger_list->pid); ret = MIN(ret, remaining); cp += ret; }//这个写socket不知道干啥的,最好加log看一下,这个是啥 ret = TEMP_FAILURE_RETRY(write(sock, buffer, cp - buffer)); int write_errno = errno; if (ret <= 0) { close(sock); if (ret == -1) { return -write_errno; } if (ret == 0) { return -EIO; } return ret; }//交换了fd 和sock,把socket值送给logger_list ret = atomic_exchange(&logger_list->fd, sock); if ((ret > 0) && (ret != sock)) { close(ret); } return sock;}
2.6 android_log_printLogLine写log文件联合体成员变量公用其实内存,因此recv到log_msg时,会把值同时对两个赋值。此时entry端会先赋值,buffer比较大,需要得到message真正在log_msg中的位置
struct logger_entry { uint16_t len; uint16_t hdr_size; int32_t pid; uint32_t tid; uint32_t sec; uint32_t nsec; uint32_t lid; uint32_t uid; };struct log_msg { union {//联合体成员变量公用其实内存 unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1]; struct logger_entry entry; } __attribute__((aligned(4)));//4字节对齐...};
转到AndroidLogEntry,需要找到各个变量在log_msg中的起始位置
typedef struct AndroidLogEntry_t { time_t tv_sec; long tv_nsec; android_LogPriority priority; int32_t uid; int32_t pid; int32_t tid; const char* tag; size_t tagLen; size_t messageLen; const char* message;} AndroidLogEntry;
android_log_processLogBuffer函数把log_msg内容,通过偏移得到log真正的内容message,同时还得到tag,优先级
log_msg内容入下
|--struct logger_entry entry --| pro | tag | msgbuffer | msg msgstart msgend
int android_log_processLogBuffer(struct logger_entry* buf, AndroidLogEntry* entry) { entry->message = NULL; entry->messageLen = 0; entry->tv_sec = buf->sec; entry->tv_nsec = buf->nsec; entry->uid = -1; entry->pid = buf->pid; entry->tid = buf->tid; if (buf->len < 3) { fprintf(stderr, "+++ LOG: entry too smalln"); return -1; } int msgStart = -1; int msgEnd = -1; int i; if (buf->hdr_size < sizeof(logger_entry)) { fprintf(stderr, "+++ LOG: hdr_size must be at least as big as struct logger_entryn"); return -1; } //msg表示buf偏移hdr_size(sizeof(struct logger_entry))个size char* msg = reinterpret_cast
int android_log_printLogLine(AndroidLogFormat* p_format, int fd, const AndroidLogEntry* entry) { int ret; char defaultBuffer[512]; char* outBuffer = NULL; size_t totalLen;//通过entry message,把buffer考到outBUffer outBuffer = android_log_formatLogLine(p_format, defaultBuffer, sizeof(defaultBuffer), entry, &totalLen); if (!outBuffer) return -1;//写outBuffer到文件,如果文件是终端,就打印终端 do { ret = write(fd, outBuffer, totalLen); } while (ret < 0 && errno == EINTR); if (ret < 0) { fprintf(stderr, "+++ LOG: write failed (errno=%d)n", errno); ret = 0; goto done; } if (((size_t)ret) < totalLen) { fprintf(stderr, "+++ LOG: write partial (%d of %d)n", ret, (int)totalLen); goto done; }done: if (outBuffer != defaultBuffer) { free(outBuffer); } return ret;}
3、logd流程 3.1 logd进程启动logd通过rc启动,需要链接库liblog和liblogd
cc_binary { name: "logd", init_rc: ["logd.rc"], srcs: ["main.cpp"], static_libs: [ "liblog", "liblogd", ], shared_libs: [ "libsysutils", "libcutils", "libbase", "libpackagelistparser", "libprocessgroup", "libcap", ], cflags: ["-Werror"],}
@logd.rcservice logd /system/bin/logd //定义需要的3个socket,已经对应权限 socket logd stream 0666 logd logd socket logdr seqpacket 0666 logd logd socket logdw dgram+passcred 0222 logd logd file /proc/kmsg r file /dev/kmsg w //文件是干啥的? user logd //用户是logd group logd system package_info readproc capabilities SYSLOG AUDIT_ConTROL priority 10 //优先级,有用? writepid /dev/cpuset/system-background/tasksservice logd-reinit /system/bin/logd --reinit oneshot disabled user logd group logd writepid /dev/cpuset/system-background/tasks# Limit SELinux denial generation to 5/secondservice logd-auditctl /system/bin/auditctl -r 5 oneshot disabled user logd group logd capabilities AUDIT_ConTROLon fs//write write /dev/event-log-tags "# content owned by logd"//改文件权限,这样其他组没有访问event-log-tags的权限 chown logd logd /dev/event-log-tags chmod 0644 /dev/event-log-tagson property:sys.boot_completed=1 start logd-auditctl
1 设置时区timezone环境变量为UTC2 获取kernel 节点fd /dev/kmsg3 启动re-init线程4 创建logBuffer, 创建LogReader并且监听logdr,创建LogListener监听logdw,创建CommandListener监听socket logd5 LogAudit并监听selinux ,创建LogKlog监听kernel
@main.cppint main(int argc, char* argv[]) { // logd is written under the assumption that the timezone is UTC. // If TZ is not set, persist.sys.timezone is looked up in some time utility // libc functions, including mktime、It confuses the logd time handling, // so here explicitly set TZ to UTC, which overrides the property. setenv("TZ", "UTC", 1); //设置timezone为utc,害怕时间突变 // issue reinit command、KISS argument parsing. if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) { return issueReinit(); }//kernel log节点文件,获取kmsg文件fd fdDmesg static const char dev_kmsg[] = "/dev/kmsg"; fdDmesg = android_get_control_file(dev_kmsg); if (fdDmesg < 0) { fdDmesg = TEMP_FAILURE_RETRY(open(dev_kmsg, O_WRonLY | O_CLOEXEC)); } int fdPmesg = -1; //感觉是false,没有此属性 bool klogd = __android_logger_property_get_bool( "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE); if (klogd) { static const char proc_kmsg[] = "/proc/kmsg"; fdPmesg = android_get_control_file(proc_kmsg); if (fdPmesg < 0) { fdPmesg = TEMP_FAILURE_RETRY( open(proc_kmsg, O_RDonLY | O_NDELAY | O_CLOEXEC)); } if (fdPmesg < 0) android::prdebug("Failed to open %sn", proc_kmsg); }//selinux权限 bool auditd = __android_logger_property_get_bool("ro.logd.auditd", BOOL_DEFAULT_TRUE); if (DropPrivs(klogd, auditd) != 0) { return EXIT_FAILURE; } // Reinit Thread sem_init(&reinit, 0, 0); pthread_attr_t attr; if (!pthread_attr_init(&attr)) { struct sched_param param; memset(¶m, 0, sizeof(param)); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setschedpolicy(&attr, SCHED_BATCH); //创建reinit_thread if (!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) { pthread_t thread; reinit_running = true; if (pthread_create(&thread, &attr, reinit_thread_start, nullptr)) { reinit_running = false; } } pthread_attr_destroy(&attr); } // Serves the purpose of managing the last logs times read on a // socket connection, and as a reader lock on a range of log // entries. LastLogTimes* times = new LastLogTimes(); // LogBuffer is the object which is responsible for holding all // log entries.//创建logBuffer logBuf = new LogBuffer(times); signal(SIGHUP, reinit_signal_handler); //启动统计 if (__android_logger_property_get_bool( "logd.statistics", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_PERSIST | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) { logBuf->enableStatistics(); } // LogReader listens on /dev/socket/logdr、When a client // connects, log entries in the LogBuffer are written to the client.//logReader监听logdr socket,客户端写的时候需要知道连接内容 LogReader* reader = new LogReader(logBuf); if (reader->startListener()) { return EXIT_FAILURE; } // LogListener listens on /dev/socket/logdw for client // initiated log messages、New log entries are added to LogBuffer // and LogReader is notified to send updates to connected clients.//初始化logListener LogListener* swl = new LogListener(logBuf, reader); // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value if (swl->startListener(600)) { return EXIT_FAILURE; } // Command listener listens on /dev/socket/logd for incoming logd // administrative commands.//CommandListener初始化监听logd socket CommandListener* cl = new CommandListener(logBuf, reader, swl); if (cl->startListener()) { return EXIT_FAILURE; } // LogAudit listens on NETlink_AUDIT socket for selinux // initiated log messages、New log entries are added to LogBuffer // and LogReader is notified to send updates to connected clients.//selinux LogAudit* al = nullptr; if (auditd) { al = new LogAudit(logBuf, reader, __android_logger_property_get_bool( "ro.logd.auditd.dmesg", BOOL_DEFAULT_TRUE) ? fdDmesg : -1); }//kernel log每个都会传入静态logBuf对象 LogKlog* kl = nullptr; if (klogd) { kl = new LogKlog(logBuf, reader, fdDmesg, fdPmesg, al != nullptr); }//读取dmesg readDmesg(al, kl); // failure is an option ..、messages are in dmesg (required by standard)//LogKlog和LogAudit都启动listener if (kl && kl->startListener()) { delete kl; } if (al && al->startListener()) { delete al; } TEMP_FAILURE_RETRY(pause()); return EXIT_SUCCESS;}
3.2 logd-reinit进程和 re-init线程logd.rc中启动logd-reinit 如下:
service logd-reinit /system/bin/logd --reinit oneshot disabled user logd group logd writepid /dev/cpuset/system-background/tasks
启动logd-reinit的服务,主要工作是重新初始化logd的LogBuffer,在上面的启动脚本中,配置为oneshot,即开机只执行一次。
通过上面logd的初始化,可以看到,logd启动后,创建了一个线程reinit_thread_start(),当logd-reinit 传入参数 reinit后,进行功能执行。logd-reinit两个步骤:
如果reinit启动后,并且/deg/kmsg打开成功,把 logd.daemon: renit写入kmsg
重新初始化各个log buffer的大小,以及其他参数的初始化,但不会重新生成LogBuffer对象
3.3 LogListener监测socket logdwLogListener继承sysutils库中的SocketListener,需要重写监听到socket变化后的回调接口onDataAvailable
@systemcorelogdLogListener.h#include
LogListener构造器就会获取socket logdw
//SocketListener传入socket etLogSocket()//buffer 和reader也赋值到 logbuf, readerLogListener::LogListener(LogBuffer* buf, LogReader* reader) : SocketListener(getLogSocket(), false), logbuf(buf), reader(reader) {}//获取到socketint 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;}
startListener开始监听,创建监听线程threadStart,调用runListener,此时创建fdspoll,mClients 是客户端连接socket内容。然后调用poll轮询vector fds数组,看是否变化,
@systemcorelibsysutilssrcSocketListener.cpp//backlog默认4,LogListenner默认600int SocketListener::startListener(int backlog) { //mSock是fd,不走这两个if if (!mSocketName && mSock == -1) { SLOGE("Failed to start unbound listener"); errno = EINVAL; return -1; } else if (mSocketName) { if ((mSock = android_get_control_socket(mSocketName)) < 0) { SLOGE("Obtaining file descriptor socket '%s' failed: %s", mSocketName, strerror(errno)); return -1; } SLOGV("got mSock = %d for %s", mSock, mSocketName); fcntl(mSock, F_SETFD, FD_CLOEXEC); } if (mListen && listen(mSock, backlog) < 0) { SLOGE("Unable to listen on socket (%s)", strerror(errno)); return -1; } else if (!mListen) //保存键值对mSockfd和SocketClient* mClients[mSock] = new SocketClient(mSock, false, mUseCmdNum); //piple创建 if (pipe2(mCtrlPipe, O_CLOEXEC)) { SLOGE("pipe failed (%s)", strerror(errno)); return -1; } //开启线程,防止阻塞主线程 if (pthread_create(&mThread, nullptr, SocketListener::threadStart, this)) { SLOGE("pthread_create (%s)", strerror(errno)); return -1; } return 0;}//线程运行对象类SocketListener函数方法runListenervoid *SocketListener::threadStart(void *obj) { SocketListener *me = reinterpret_cast
onDataAvailable是收到socket变化的回调,通过组装iovec,读取socket内容,得到文件头id tid time 和内容msg.然后写到logbuffer最后通知有log写入
@LogListener.cppbool LogListener::onDataAvailable(SocketClient* cli) { static bool name_set; if (!name_set) { prctl(PR_SET_NAME, "logd.writer"); //设置线程名 name_set = true; } // + 1 to ensure null terminator if MAX_PAYLOAD buffer is received 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, }; //获取client socket int socket = cli->getSocket(); // 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);//socket内容写到hdr中,会把log内容放到iov里面,此时值就是buffer if (n <= (ssize_t)(sizeof(android_log_header_t))) { return false; } buffer[n] = 0; struct ucred* cred = nullptr; struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); while (cmsg != nullptr) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) { cred = (struct ucred*)CMSG_DATA(cmsg); break; } cmsg = CMSG_NXTHDR(&hdr, cmsg); } if (cred == nullptr) { return false; } if (cred->uid == AID_LOGD) { // ignore log messages we send to ourself. // Such log messages are often generated by libraries we depend on // which use standard Android logging. return false; } android_log_header_t* header = reinterpret_cast(buffer); log_id_t logId = static_cast
通知logReader有消息,然后刷新命令flushCommand
@androidsystemcorelogdLogReader.cpp// When we are notified a new log entry is available, inform// listening sockets who are watching this entry's log id.void LogReader::notifyNewLog(log_mask_t logMask) { FlushCommand command(*this, logMask); runOnEachSocket(&command);}
void SocketListener::runonEachSocket(SocketClientCommand *command) { for (SocketClient* c : snapshotClients()) { command->runSocketCommand(c); c->decRef(); }}
3.4 LogReader监测socket logdrLogReader和LogListenner差不多,都继承SocketListener,重写onDataAvailable回调
class LogReader : public SocketListener { LogBuffer& mLogbuf; public: explicit LogReader(LogBuffer* logbuf); void notifyNewLog(log_mask_t logMask); LogBuffer& logbuf(void) const { return mLogbuf; } protected: virtual bool onDataAvailable(SocketClient* cli); private: static int getLogSocket(); void doSocketDelete(SocketClient* cli);};
@LogReader.cpp// Note returning false will release the SocketClient instance.// logdr改变,传入改变的client,可以知道客户端的socket fd(logdr),以及进程pid// onDataAvailable数据改变回调,由于logd是服务端,只能接收客户端写logdr socket回到,也就是只会接收logcat打开,写命令的那一条数据,正常只有一次bool LogReader::onDataAvailable(SocketClient* cli) { static bool name_set; if (!name_set) { prctl(PR_SET_NAME, "logd.reader");//设置线程 name_set = true; } char buffer[255];//读取socket内容,看起来就是logcat连接时发送的那一串tail start timeout等,好赋值给logd int len = read(cli->getSocket(), buffer, sizeof(buffer) - 1); if (len <= 0) { doSocketDelete(cli); return false; } buffer[len] = ''; // Clients are only allowed to send one command, disconnect them if they // send another. LogTimeEntry::wrlock(); for (const auto& entry : mLogbuf.mTimes) { if (entry->mClient == cli) { entry->release_Locked(); LogTimeEntry::unlock(); return false; } } LogTimeEntry::unlock(); unsigned long tail = 0; static const char _tail[] = " tail="; char* cp = strstr(buffer, _tail); if (cp) { tail = atol(cp + sizeof(_tail) - 1); } log_time start(log_time::EPOCH); static const char _start[] = " start="; cp = strstr(buffer, _start); if (cp) { // Parse errors will result in current time start.strptime(cp + sizeof(_start) - 1, "%s.%q"); } uint64_t timeout = 0; static const char _timeout[] = " timeout="; cp = strstr(buffer, _timeout); if (cp) { timeout = atol(cp + sizeof(_timeout) - 1) * NS_PER_SEC + log_time(CLOCK_REALTIME).nsec(); } unsigned int logMask = -1; static const char _logIds[] = " lids="; cp = strstr(buffer, _logIds); if (cp) { logMask = 0; cp += sizeof(_logIds) - 1; while (*cp && *cp != '') { int val = 0; while (isdigit(*cp)) { val = val * 10 + *cp - '0'; ++cp; } logMask |= 1 << val; if (*cp != ',') { break; } ++cp; } } pid_t pid = 0; static const char _pid[] = " pid="; cp = strstr(buffer, _pid); if (cp) { pid = atol(cp + sizeof(_pid) - 1); } bool nonBlock = false; if (!fastcmp
正在的写logdr地方
systemcorelogdLogTimes.cpp//启动线程threadStartbool LogTimeEntry::startReader_Locked() { pthread_attr_t attr; if (!pthread_attr_init(&attr)) { if (!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) { if (!pthread_create(&mThread, &attr, LogTimeEntry::threadStart, this)) { pthread_attr_destroy(&attr); return true; } } pthread_attr_destroy(&attr); } return false;}//logd.reader.per线程真正启动void* LogTimeEntry::threadStart(void* obj) { prctl(PR_SET_NAME, "logd.reader.per");//set name LogTimeEntry* me = reinterpret_cast
top -H -p 271(logd pid) 查看logd线程信息入下
Threads: 8 total, 0 running, 8 sleeping, 0 stopped, 0 zombie Mem: 3390188K total, 2663680K used, 726508K free, 19460096 buffers Swap: 2097148K total, 0 used, 2097148K free, 733840K cached800%cpu 10%user 1%nice 42%sys 744%idle 0%iow 2%irq 1%sirq 0%host TID USER PR NI VIRT RES SHR S[%CPU] %MEM TIME+ THREAD PROCESS 2947 logd 30 10 12G 6.7M 2.6M S 0.0 0.2 0:04.40 logd.reader.per logd //LogTimes.cpp里面的线程 283 logd 30 10 12G 6.7M 2.6M S 0.0 0.2 0:00.95 logd.klogd logd //kernel线程 284 logd 30 10 12G 6.7M 2.6M S 0.0 0.2 0:00.02 logd.auditd logd //avc selinux线程 277 logd 30 10 12G 6.7M 2.6M S 0.0 0.2 0:08.91 logd.writer logd // LogListener线程 socket logdw 278 logd 30 10 12G 6.7M 2.6M S 0.0 0.2 0:00.00 logd.control logd //CommandListener.cpp logd控制线程 socket logd 274 logd 30 10 12G 6.7M 2.6M S 0.0 0.2 0:00.00 logd.daemon logd //reinit_thread_start线程 prctl(PR_SET_NAME, "logd.daemon"); 276 logd 30 10 12G 6.7M 2.6M S 0.0 0.2 0:00.00 logd.reader logd //logReader线程 271 logd 30 10 12G 6.7M 2.6M S 0.0 0.2 0:00.02 logd logd //主线程
debuggerd -b 271 命令查看271进程trace
msmnile_gvmq:/ # debuggerd -b 271----- pid 271 at 2022-01-18 21:35:49 -----Cmd line: /system/bin/logdABI: 'arm64'"logd" sysTid=271 #00 pc 000000000009bad8 /apex/com.android.runtime/lib64/bionic/libc.so (__rt_sigsuspend+8) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #01 pc 000000000005c96c /apex/com.android.runtime/lib64/bionic/libc.so (sigsuspend64+60) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #02 pc 000000000005a050 /apex/com.android.runtime/lib64/bionic/libc.so (pause+36) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #03 pc 0000000000009800 /system/bin/logd (main+1496) (BuildId: dbc7ca087ee748266e4ea9e71fc705e4) #04 pc 00000000000499fc /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+108) (BuildId: 8d0a10271eef02de6c33b788fec2db37)"logd.daemon" sysTid=274 #00 pc 000000000004b4cc /apex/com.android.runtime/lib64/bionic/libc.so (syscall+28) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #01 pc 000000000004f0b4 /apex/com.android.runtime/lib64/bionic/libc.so (__futex_wait_ex(void volatile*, bool, int, bool, timespec const*)+144) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #02 pc 000000000005bea4 /apex/com.android.runtime/lib64/bionic/libc.so (sem_wait+116) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #03 pc 0000000000009934 /system/bin/logd (reinit_thread_start(void*)+96) (BuildId: dbc7ca087ee748266e4ea9e71fc705e4) #04 pc 00000000000afecc /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+64) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #05 pc 0000000000050408 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: 8d0a10271eef02de6c33b788fec2db37)"logd.reader" sysTid=276 #00 pc 000000000009c1b4 /apex/com.android.runtime/lib64/bionic/libc.so (__ppoll+4) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #01 pc 000000000005a3c0 /apex/com.android.runtime/lib64/bionic/libc.so (poll+92) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #02 pc 000000000000570c /system/lib64/libsysutils.so (SocketListener::runListener()+412) (BuildId: 56450a0b5452b4d4ef534a38279ded2e) #03 pc 00000000000053c4 /system/lib64/libsysutils.so (SocketListener::threadStart(void*)+8) (BuildId: 56450a0b5452b4d4ef534a38279ded2e) #04 pc 00000000000afecc /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+64) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #05 pc 0000000000050408 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: 8d0a10271eef02de6c33b788fec2db37)"logd.writer" sysTid=277 #00 pc 000000000009c1b4 /apex/com.android.runtime/lib64/bionic/libc.so (__ppoll+4) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #01 pc 000000000005a3c0 /apex/com.android.runtime/lib64/bionic/libc.so (poll+92) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #02 pc 000000000000570c /system/lib64/libsysutils.so (SocketListener::runListener()+412) (BuildId: 56450a0b5452b4d4ef534a38279ded2e) #03 pc 00000000000053c4 /system/lib64/libsysutils.so (SocketListener::threadStart(void*)+8) (BuildId: 56450a0b5452b4d4ef534a38279ded2e) #04 pc 00000000000afecc /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+64) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #05 pc 0000000000050408 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: 8d0a10271eef02de6c33b788fec2db37)"logd.control" sysTid=278 #00 pc 000000000009c1b4 /apex/com.android.runtime/lib64/bionic/libc.so (__ppoll+4) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #01 pc 000000000005a3c0 /apex/com.android.runtime/lib64/bionic/libc.so (poll+92) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #02 pc 000000000000570c /system/lib64/libsysutils.so (SocketListener::runListener()+412) (BuildId: 56450a0b5452b4d4ef534a38279ded2e) #03 pc 00000000000053c4 /system/lib64/libsysutils.so (SocketListener::threadStart(void*)+8) (BuildId: 56450a0b5452b4d4ef534a38279ded2e) #04 pc 00000000000afecc /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+64) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #05 pc 0000000000050408 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: 8d0a10271eef02de6c33b788fec2db37)"logd.klogd" sysTid=283 #00 pc 000000000009ae74 /apex/com.android.runtime/lib64/bionic/libc.so (read+4) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #01 pc 000000000001cd0c /system/bin/logd (LogKlog::onDataAvailable(SocketClient*)+156) (BuildId: dbc7ca087ee748266e4ea9e71fc705e4) #02 pc 0000000000005aa8 /system/lib64/libsysutils.so (SocketListener::runListener()+1336) (BuildId: 56450a0b5452b4d4ef534a38279ded2e) #03 pc 00000000000053c4 /system/lib64/libsysutils.so (SocketListener::threadStart(void*)+8) (BuildId: 56450a0b5452b4d4ef534a38279ded2e) #04 pc 00000000000afecc /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+64) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #05 pc 0000000000050408 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: 8d0a10271eef02de6c33b788fec2db37)"logd.auditd" sysTid=284 #00 pc 000000000009c1b4 /apex/com.android.runtime/lib64/bionic/libc.so (__ppoll+4) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #01 pc 000000000005a3c0 /apex/com.android.runtime/lib64/bionic/libc.so (poll+92) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #02 pc 000000000000570c /system/lib64/libsysutils.so (SocketListener::runListener()+412) (BuildId: 56450a0b5452b4d4ef534a38279ded2e) #03 pc 00000000000053c4 /system/lib64/libsysutils.so (SocketListener::threadStart(void*)+8) (BuildId: 56450a0b5452b4d4ef534a38279ded2e) #04 pc 00000000000afecc /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+64) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #05 pc 0000000000050408 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: 8d0a10271eef02de6c33b788fec2db37)"logd.reader.per" sysTid=2947 #00 pc 000000000004b4cc /apex/com.android.runtime/lib64/bionic/libc.so (syscall+28) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #01 pc 000000000004f0b4 /apex/com.android.runtime/lib64/bionic/libc.so (__futex_wait_ex(void volatile*, bool, int, bool, timespec const*)+144) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #02 pc 00000000000af2b4 /apex/com.android.runtime/lib64/bionic/libc.so (pthread_cond_wait+60) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #03 pc 0000000000010508 /system/bin/logd (LogTimeEntry::threadStart(void*)+684) (BuildId: dbc7ca087ee748266e4ea9e71fc705e4) #04 pc 00000000000afecc /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+64) (BuildId: 8d0a10271eef02de6c33b788fec2db37) #05 pc 0000000000050408 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: 8d0a10271eef02de6c33b788fec2db37)----- end 271 -----
主线程使用stack命令解析是在pause,等待信号 对应代码TEMP_FAILURE_RETRY(pause());
----- pid 271 at 2022-01-18 21:35:49 -----Cmd line: /system/bin/logdABI: 'arm64'Stack Trace: RELADDR FUNCTION FILE:LINE 000000000009bad8 __rt_sigsuspend+8 out/soong/.intermediates/bionic/libc/syscalls-arm64.S/gen/syscalls-arm64.S:1704 000000000005c96c sigsuspend64+60 bionic/libc/bionic/signal.cpp:270 000000000005a050 pause+36 bionic/libc/bionic/pause.cpp:34 0000000000009800 main+1496 system/core/logd/main.cpp:436 00000000000499fc __libc_init+108 bionic/libc/bionic/libc_init_dynamic.cpp:151
logd.reader线程SocketListener::threadStart在poll消息
"logd.reader" sysTid=276Stack Trace: RELADDR FUNCTION FILE:LINE 000000000009c1b4 __ppoll+4 out/soong/.intermediates/bionic/libc/syscalls-arm64.S/gen/syscalls-arm64.S:2385 000000000005a3c0 poll+92 bionic/libc/bionic/poll.cpp:48 v--------------> poll(pollfd*, unsigned int pass_object_size1, int) bionic/libc/include/bits/fortify/poll.h:54 000000000000570c SocketListener::runListener()+412 system/core/libsysutils/src/SocketListener.cpp:168 00000000000053c4 SocketListener::threadStart(void*)+8 system/core/libsysutils/src/SocketListener.cpp:146 00000000000afecc __pthread_start(void*)+64 bionic/libc/bionic/pthread_create.cpp:347 0000000000050408 __start_thread+64
logd.writer也是在poll线程
"logd.writer" sysTid=277Stack Trace: RELADDR FUNCTION FILE:LINE 000000000009c1b4 __ppoll+4 out/soong/.intermediates/bionic/libc/syscalls-arm64.S/gen/syscalls-arm64.S:2385 000000000005a3c0 poll+92 bionic/libc/bionic/poll.cpp:48 v--------------> poll(pollfd*, unsigned int pass_object_size1, int) bionic/libc/include/bits/fortify/poll.h:54 000000000000570c SocketListener::runListener()+412 system/core/libsysutils/src/SocketListener.cpp:168 00000000000053c4 SocketListener::threadStart(void*)+8 system/core/libsysutils/src/SocketListener.cpp:146 00000000000afecc __pthread_start(void*)+64 bionic/libc/bionic/pthread_create.cpp:347 0000000000050408 __start_thread+64 bionic/libc/bionic/clone.cpp:53
logd.klogd线程收到了数据回调onDataAvailable,正在读取数据
"logd.klogd" sysTid=283Stack Trace: RELADDR FUNCTION FILE:LINE 000000000009ae74 read+4 out/soong/.intermediates/bionic/libc/syscalls-arm64.S/gen/syscalls-arm64.S:461 v--------------> read(int, void*, unsigned long pass_object_size0) bionic/libc/include/bits/fortify/unistd.h:159 000000000001cd0c LogKlog::onDataAvailable(SocketClient*)+156 system/core/logd/LogKlog.cpp:235 0000000000005aa8 SocketListener::runListener()+1336 system/core/libsysutils/src/SocketListener.cpp:218 00000000000053c4 SocketListener::threadStart(void*)+8 system/core/libsysutils/src/SocketListener.cpp:146 00000000000afecc __pthread_start(void*)+64 bionic/libc/bionic/pthread_create.cpp:347 0000000000050408 __start_thread+64 bionic/libc/bionic/clone.cpp:53
4、整体流程图