Android logger System 由misc的logger driver和相关framework接口组成, 与syslog相比, 它区分了4种不同事件类型, 不同的事件类型有各自的kernel space的循环缓冲来提供, 这样的log更加清晰,对于user space端来说更加友好. 目前logger driver正在寻求被kernel main stream所接受, 不久的将来将会merge到main stream.
驱动层的实现
定义了4个不同的事件类型: main, event, radio, system. 它们都作为misc驱动存在, 初始之后,在/dev/log/下能看到4个对应的设备文件
4个循环缓冲, 大小在编译内核的时候就指定了,如下
DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 64*1024) DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024) DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 64*1024) DEFINE_LOGGER_DEVICE(log_system, LOGGER_LOG_SYSTEM, 64*1024)
支持同步,异步读写并通过fix_up_readers来减少旧log被覆盖的可能性.与其它android的自定义的software driver一样, 也提供了一些实用的ioctl来给用户层使用.
LOGGER_GET_LOG_BUF_SIZE LOGGER_GET_LOG_LEN LOGGER_GET_NEXT_ENTRY_LEN LOGGER_FLUSH_LOG
其中使用了wait queue来进行读写之间的控制.
每条log都由driver来记录相应的pid, tgid及timestamp, 同时, 用户层会提供相应的level, tag及具体的log内容.
实现的代码相对简单, 这里就详细解释了:)
framework层的接口
从上图很清楚的可以看出, android的logger系统主要由4个部分组成:
logger driver, 就是第一部分所介绍的log设备
logger framework, 为其它几个部分交互及扩展开发提供的中间层
logcat, 用户态的log读取工具
ddms extension, 与ADT集成的可视化log reader
如上所述,总共有4种类型的log, 其中event的log是以binary的形式来记录的, 所以在读取它的时候需要做额外处理.
这点从liblog下的logd_write.c中的write log函数就可以看出来了.
__android_log_write
__android_log_bwrite
应用程序通常使用的是android.util.Log class, 而event log使用的是android.util.Event class, 它比较特殊,对应与其中binary的tags的数据在/system/etc/event-log-tags中.
system event对应的使用的是android.util.Slog class, 这里大家没有看到radio对应的log类, 是因为framework自动通过分析所有现有log中的tag,radio相关的信息放入对应的radio设备中.
如liblog/log_write.c中:
/* XXX: This needs to go! */ if (!strcmp(tag, "HTC_RIL") || !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */ !strcmp(tag, "AT") || !strcmp(tag, "GSM") || !strcmp(tag, "STK") || !strcmp(tag, "CDMA") || !strcmp(tag, "PHONE") || !strcmp(tag, "SMS")) bufID = LOG_ID_RADIO;
还可以通过在init.rc指定
service logcat /system/bin/logcat -f /dev/kmsg oneshot
来使得所有logger所产生的log写入dmsg的空间.而不是独立于通常的kernel log空间.
关于ddms与liblog的接口的相关实现,参见system/core/logcat/及sdk/ddms/libs/下的实现.ddms即host端是通过调用adb logcat来与device交互,从而获得device端的各种log,再映射到eclipse的ADT中.
其它,
nonseekable_open, 用来实现不需要支持seek动作的文件的打开动作
wait queue, 使用了kernel提供的sleep/wake的wait queue机制, 关于wait queue参见<Linux.Kernel.Development>的第四章, Sleeping and Waking up
参考资料:
Android Logger
Android Logging System
<Android Internals: System> 2.3.4
RFC: android logger feedback request