Android10系统源码的libc中添加日志输出接口
The following article is from 卓码空间 Author QDroid88888
一、libc中日志输出讨论
安卓源码libc中,默认提供了日志调试输出接口。源码位于如下:
//头文件定义
bionic/libc/async_safe/include/async_safe/log.h
//实现文件
bionic/libc/async_safe/async_safe_log.cpp
通过async_safe_log.cpp代码分析,写入日志主要是使用UNIX domain socket建立到域"/dev/socket/logdw"的通信,然后写入日志数据。核心逻辑代码如下:
//正在写入日志的方法,主要调用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;
}
由于以上方法用着不是很爽,下面将通过"#define"定义几个常用的日志打印宏定义。
二、方便日志输出接口定义
参照平时ndk开发中LOGD/LOGI/LOGE的宏定义,在bionic/libc/async_safe/include/async_safe/log.h文件中定义如下方便libc中调用的日志接口。如下所示:
三、在libc中的open函数中调用
四、测试效果
编译刷机之后,终端日志输出效果还不错:
上一篇玩转安卓10源码开发定制(19)Java核心库libcore中添加Log接口任意调用
玩转Android10源码开发文章目录:
玩转Android10源码开发定制(二)刷机操作之fastboot刷机演示
玩转Android10源码开发定制(二)刷机操作之Recovery刷机演示
玩转Android10源码开发定制(三)源码中编译手机刷机包
玩转Android10源码开发定制(五)源码编译开发中常用命令
玩转Android10源码开发定制(六)修改内核源码绕过反调试检测
玩转Android10源码开发定制(七)修改ptrace绕过反调试
玩转Android10源码开发定制(九)内置frida-gadget so文件和frida-server可执行文件到系统
玩转Android10源码开发定制(十)增加获取当前运行最顶层的Activity命令
玩转Android10源码开发定制(11)内核篇之安卓内核模块开发编译
玩转Android10源码开发定制(12)内核篇之logcat输出内核日志 玩转Android10源码开发定制(13)修改安卓源码关闭selinux
玩转Android10源码开发定制(14)修改安卓源码手机永不休眠
玩转Android10源码开发定制(15)实现跳过开机向导、插电源线不休眠等默认配置
玩转Android10源码开发定制(16)LineageOS中编译user模式的系统
玩转Android10源码开发定制(17)开发并内置具有系统权限(system)的App
欢迎各位关注公众号