1. Discussion of log output in libc
In the Android source code libc, the log debugging output interface is provided by default. The source code is located as follows:
//头文件定义
bionic/libc/async_safe/include/async_safe/log.h
//实现文件
bionic/libc/async_safe/async_safe_log.cpp
Through async_safe_log.cpp code analysis, writing to the log is mainly to use UNIX domain socket to establish communication to the domain "/dev/socket/logdw", and then write the log data. The core logic code is as follows:
//正在写入日志的方法,主要调用open_log_socket建立socket连接,然后写数据进去
int async_safe_write_log(int priority, const char* tag, const char* msg) {
int main_log_fd = open_log_socket();
if (main_log_fd == -1) {
// Try stderr instead.
return write_stderr(tag, msg);
}
iovec vec[6];
char log_id = (priority == ANDROID_LOG_FATAL) ? LOG_ID_CRASH : LOG_ID_MAIN;
vec[0].iov_base = &log_id;
vec[0].iov_len = sizeof(log_id);
uint16_t tid = gettid();
vec[1].iov_base = &tid;
vec[1].iov_len = sizeof(tid);
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
log_time realtime_ts;
realtime_ts.tv_sec = ts.tv_sec;
realtime_ts.tv_nsec = ts.tv_nsec;
vec[2].iov_base = &realtime_ts;
vec[2].iov_len = sizeof(realtime_ts);
vec[3].iov_base = &priority;
vec[3].iov_len = 1;
vec[4].iov_base = const_cast<char*>(tag);
vec[4].iov_len = strlen(tag) + 1;
vec[5].iov_base = const_cast<char*>(msg);
vec[5].iov_len = strlen(msg) + 1;
int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, sizeof(vec) / sizeof(vec[0])));
__close(main_log_fd);
return result;
}
//建立到/dev/socket/logdw的通信
static int open_log_socket() {
// ToDo: Ideally we want this to fail if the gid of the current
// process is AID_LOGD, but will have to wait until we have
// registered this in private/android_filesystem_config.h. We have
// found that all logd crashes thus far have had no problem stuffing
// the UNIX domain socket and moving on so not critical *today*.
int log_fd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
if (log_fd == -1) {
return -1;
}
union {
struct sockaddr addr;
struct sockaddr_un addrUn;
} u;
memset(&u, 0, sizeof(u));
u.addrUn.sun_family = AF_UNIX;
strlcpy(u.addrUn.sun_path, "/dev/socket/logdw", sizeof(u.addrUn.sun_path));
if (TEMP_FAILURE_RETRY(connect(log_fd, &u.addr, sizeof(u.addrUn))) != 0) {
__close(log_fd);
return -1;
}
return log_fd;
}
Since the above method is not very cool, the following will define several commonly used log printing macro definitions through "#define".
2. Convenient log output interface definition
Refer to the macro definitions of LOGD/LOGI/LOGE in the usual ndk development, and define the following log interface that is convenient to call in libc in the bionic/libc/async_safe/include/async_safe/log.h file. As follows:
Three, call in the open function in libc
Fourth, the test results
After compiling and flashing, the terminal log output effect is not bad:
Fun Android10 source code development article directory:
Fun Android10 source code development and customization (1) source code download and compile
Fun Android10 source code development and customization (2) flashing operation
Fun Android10 source code development and customization (eight) built-in Apk to the system
Fun Android10 source code development and customization (12) Kernel article logcat output kernel log Fun Android10 source code development and customization (13) Modify Android source code Turn off selinux
Welcome everyone to follow the WeChat public account