Android6的Logger日志系统
来源:互联网 发布:linux oracle 11g下载 编辑:程序博客网 时间:2024/05/28 05:15
Android2.x中Logger日志系统采用了字符设备驱动来支持,到了Android6.0已经找不到kernel/goldfish/drivers/staging/android/logger.c这一层的驱动程序了。不过上层接口还是没变的,所以顺着最顶层接口,可以一路找到6.0下Logger的实现机制。
从最上层frameworks/base/core/java/android/util/Log.java找到:
public final class Log {…… public static int d(String tag, String msg) { return println_native(LOG_ID_MAIN, DEBUG, tag, msg); }……}再从frameworks/base/core/jni/android_utilLog.cpp中找到:
static jint android_util_Log_println_native(JNIEnv* env, jobject clazz, jint bufID, jint priority, jstring tagObj, jstring msgObj){ const char* tag = NULL; const char* msg = NULL; if (msgObj == NULL) { jniThrowNullPointerException(env, "println needs a message"); return -1; } if (bufID < 0 || bufID >= LOG_ID_MAX) { jniThrowNullPointerException(env, "bad bufID"); return -1; } if (tagObj != NULL) tag = env->GetStringUTFChars(tagObj, NULL); msg = env->GetStringUTFChars(msgObj, NULL); int res = __android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg); if (tag != NULL) env->ReleaseStringUTFChars(tagObj, tag); env->ReleaseStringUTFChars(msgObj, msg); return res;}接下来就要去Runtime层找__android_log_buf_write了:system/core/liblog/logd_write.c:
int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg){ struct iovec vec[3]; …… // 将日志优先级、tag、内容赋给vec的三段 return write_to_log(bufID, vec, 3);}在文件system/core/liblog/logd_write.c的头部可以看到write_to_log是个函数指针,初始值指向__write_to_log_init:
static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;……static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr){ …… if (write_to_log == __write_to_log_init) { int ret; ret = __write_to_log_initialize(); …… write_to_log = __write_to_log_daemon; } …… return write_to_log(log_id, vec, nr);}
屏蔽掉不关键的信息,__write_to_log_init首次被执行时调用__write_to_log_initialize,之后把write_to_log指针指向了__write_to_log_daemon,之后再执行write_to_log。以后__android_log_buf_write也将通过write_to_log调用__write_to_log_daemon。
再来看__write_to_log_initialize:
static int __write_to_log_initialize(){ int i, ret = 0;#if FAKE_LOG_DEVICE for (i = 0; i < LOG_ID_MAX; i++) { char buf[sizeof("/dev/log_system")]; snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i)); log_fds[i] = fakeLogOpen(buf, O_WRONLY); }#else if (pstore_fd < 0) { pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY)); } if (logd_fd < 0) { i = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)); if (i < 0) { ret = -errno; } else if (TEMP_FAILURE_RETRY(fcntl(i, F_SETFL, O_NONBLOCK)) < 0) { ret = -errno; close(i); } else { struct sockaddr_un un; memset(&un, 0, sizeof(struct sockaddr_un)); un.sun_family = AF_UNIX; strcpy(un.sun_path, "/dev/socket/logdw"); if (TEMP_FAILURE_RETRY(connect(i, (struct sockaddr *)&un, sizeof(struct sockaddr_un))) < 0) { ret = -errno; close(i); } else { logd_fd = i; } } }#endif return ret;}
用gdb把断点设在函数首行发现直接进入了#else的部分,说明FAKE_LOG_DEVICE或者没定义,或者定义为0,以后都可以忽略。接下来创建scoket并连接/dev/socket/logdw,并将套接字赋给logd_fd。以后的日志都写到了logd_fd中。
所以研究Android6.0的日志系统在内核层应该去找/dev/socket/logdw的驱动。
写了个简单的程序从Runtime层由上往下跟进:
#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <android/log.h>#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "keymatch", __VA_ARGS___)int main(int argc, const char** argv){ __android_log_write(ANDROID_LOG_INFO, "LOG", "ABCDEF"); printf("123456"); return 0;}Android.mk文件需要注意,加上链接libs:
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE_TAGS := optionalLOCAL_LDLIBS := -llogLOCAL_MODULE := testlog LOCAL_SRC_FILES := $(call all-subdir-c-files)include $(BUILD_EXECUTABLE)
__android_log_write这个函数定义在logd_write.c中:
int __android_log_write(int prio, const char *tag, const char *msg){ return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);}当我用gdb step in 到__android_log_buf_write时,却怎么也进不去:
(gdb) b mainBreakpoint 1 at 0x614: file external/testlog/testlog.c, line 10.(gdb) cThe program is not being run.(gdb) target remote :1234Remote debugging using :1234warning: Unable to find dynamic linker breakpoint function.GDB will be unable to debug shared library initializersand track explicitly loaded dynamic code.Cannot access memory at address 0x00xb6ef6658 in ?? ()(gdb) cContinuing.warning: Could not load shared library symbols for 6 libraries, e.g. /system/bin/linker.Use the "info sharedlibrary" command to see the complete listing.Do you need "set solib-search-path" or "set sysroot"?Breakpoint 1, main (argc=1, argv=0xbee3dba4) at external/testlog/testlog.c:1010 __android_log_write(ANDROID_LOG_INFO, "LOG", "ABCDEF");(gdb) set solib-absolute-prefix out/target/product/generic/symbwarning: Unable to find dynamic linker breakpoint function.GDB will be unable to debug shared library initializersand track explicitly loaded dynamic code.(gdb) set solib-absolute-prefix out/target/product/generic/symbols/Reading symbols from out/target/product/generic/symbols/system/bin/linker...done.Loaded symbols for out/target/product/generic/symbols/system/bin/linkerReading symbols from out/target/product/generic/symbols/system/lib/libc++.so...done.Loaded symbols for out/target/product/generic/symbols/system/lib/libc++.soReading symbols from out/target/product/generic/symbols/system/lib/libc.so...done.Loaded symbols for out/target/product/generic/symbols/system/lib/libc.soReading symbols from out/target/product/generic/symbols/system/lib/libm.so...done.Loaded symbols for out/target/product/generic/symbols/system/lib/libm.soReading symbols from out/target/product/generic/symbols/system/lib/liblog.so...done.Loaded symbols for out/target/product/generic/symbols/system/lib/liblog.soReading symbols from out/target/product/generic/symbols/system/lib/libnetd_client.so...done.Loaded symbols for out/target/product/generic/symbols/system/lib/libnetd_client.so(gdb) n9 {(gdb) n10 __android_log_write(ANDROID_LOG_INFO, "LOG", "ABCDEF");(gdb) s__android_log_write (prio=4, tag=0xb6f18070 "LOG", msg=0xb6f18074 "ABCDEF") at system/core/liblog/logd_write.c:359359 {(gdb) s360 return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);(gdb) si0xb6d8bcd2 360 return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);(gdb)0xb6d8bcd4 360 return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);(gdb)361 }(gdb)无论使用s或者si都不行,我判断应该是因为__android_log_buf_write被调用的次数不多,因此被编译器内联了。不过没关系,这只是个过路函数,它内部调用了write_to_log,这是个函数指针,凡是被函数指针指过的函数,应该都不会被内联。因为被内联的函数相当于代码展开,函数不存在了,也就无法被函数指针指向。因此,可以把断点端到write_to_log所指向的__write_to_log_initialize和__write_to_log_daemon。
0 0
- Android6的Logger日志系统
- Android 简单的Logger 日志系统实现
- Android Logger日志系统
- Python基于logger模块的日志输出系统
- Logger:封装系统log的日志打印工具
- logger的系统
- Android日志系统驱动程序Logger源代码分析
- Android日志系统驱动程序Logger源代码分析
- Android日志系统驱动程序Logger源代码分析
- Android日志系统驱动程序Logger源代码分析
- Android日志系统驱动程序Logger源代码分析
- Logger日志系统实现流程研究
- Android日志系统驱动程序Logger源代码分析
- Android日志系统驱动程序Logger源代码分析
- Android日志系统驱动程序Logger源代码分析
- Android日志系统驱动程序Logger源代码分析
- Android日志系统驱动程序Logger源代码分析
- Android日志系统驱动程序Logger源代码分析
- 华为oj 字符串匹配
- Codeforces 151A Soft Drinking 【水题】
- CNTK学习笔记(二)
- HDU 2048 数塔
- mysqldump 参数说明
- Android6的Logger日志系统
- studio使用
- Python IDLE无法显示行号、Python IDLE shell里运行py文件
- Java POI通过模板方法生成word文档
- BestCoder Round #74 (div.2 b) hdu5636 Shortest Path 【dfs】
- 历届试题 连号区间数
- 关于内存
- eclipse使用经验(一)运行不了
- C++中头文件嵌套定义问题