Android日志系统驱动程序Logger源代码分析
Android日志系统驱动程序Logger源代码分析
我们知道,在Android系统中,提供了一个轻量级的日志系统,这个日志系统是以驱动程序的形式实现在内核空间的,而在用户空间分别提供了Java接口和C/C++接口来使用这个日志系统,取决于你编写的是Android应用程序还是系统组件。在前面的文章浅谈Android系统开发中LOG的使用中,已经简要地介绍了在Android应用程序开发中Log的使用方法,在这一篇文章中,我们将更进一步地分析Logger驱动程序的源代码,使得我们对Android日志系统有一个深刻的认识。
既然Android 日志系统是以驱动程序的形式实现在内核空间的,我们就需要获取Android内核源代码来分析了,请参照前面在Ubuntu上下载、编译和安装Android最新源代码和在Ubuntu上下载、编译和安装Android最新内核源代码(Linux Kernel)两篇文章,下载好Android源代码工程。Logger驱动程序主要由两个文件构成,分别是:
kernel/common/drivers/staging/android/logger.h
kernel/common/drivers/staging/android/logger.c
接下来,我们将分别介绍Logger驱动程序的相关数据结构,然后对Logger驱动程序源代码进行情景分析,分别日志系统初始化情景、日志读取情景和日志写入情景。
一. Logger驱动程序的相关数据结构。
我们首先来看logger.h头文件的内容:
- #ifndef _LINUX_LOGGER_H
- #define _LINUX_LOGGER_H
- #include <linux/types.h>
- #include <linux/ioctl.h>
- struct logger_entry {
- __u16 len; /* length of the payload */
- __u16 __pad; /* no matter what, we get 2 bytes of padding */
- __s32 pid; /* generating process's pid */
- __s32 tid; /* generating process's tid */
- __s32 sec; /* seconds since Epoch */
- __s32 nsec; /* nanoseconds */
- char msg[0]; /* the entry's payload */
- };
- #define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */
- #define LOGGER_LOG_EVENTS "log_events" /* system/hardware events */
- #define LOGGER_LOG_MAIN "log_main" /* everything else */
- #define LOGGER_ENTRY_MAX_LEN (4*1024)
- #define LOGGER_ENTRY_MAX_PAYLOAD \
- (LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))
- #define __LOGGERIO 0xAE
- #define LOGGER_GET_LOG_BUF_SIZE _IO(__LOGGERIO, 1) /* size of log */
- #define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */
- #define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */
- #define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */
- #endif /* _LINUX_LOGGER_H */
接着定义两个宏:
#define LOGGER_ENTRY_MAX_LEN (4*1024)
#define LOGGER_ENTRY_MAX_PAYLOAD \
(LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))
从这两个宏可以看出,每条日志记录的有效负载长度加上结构体logger_entry的长度不能超过4K个字节。
logger.h文件中还定义了其它宏,读者可以自己分析,在下面的分析中,碰到时,我们也会详细解释。
再来看logger.c文件中,其它相关数据结构的定义:
- /*
- * struct logger_log - represents a specific log, such as 'main' or 'radio'
- *
- * This structure lives from module insertion until module removal, so it does
- * not need additional reference counting. The structure is protected by the
- * mutex 'mutex'.
- */
- struct logger_log {
- unsigned char * buffer; /* the ring buffer itself */
- struct miscdevice misc; /* misc device representing the log */
- wait_queue_head_t wq; /* wait queue for readers */
- struct list_head readers; /* this log's readers */
- struct mutex mutex; /* mutex protecting buffer */
- size_t w_off; /* current write head offset */
- size_t head; /* new readers start here */
- size_t size; /* size of the log */
- };
- /*
- * struct logger_reader - a logging device open for reading
- *
- * This object lives from open to release, so we don't need additional
- * reference counting. The structure is protected by log->mutex.
- */
- struct logger_reader {
- struct logger_log * log; /* associated log */
- struct list_head list; /* entry in logger_log's list */
- size_t r_off; /* current read head offset */
- };
- /* logger_offset - returns index 'n' into the log via (optimized) modulus */
- #define logger_offset(n) ((n) & (log->size - 1))
结构体struct logger_reader用来表示一个读取日志的进程,log成员变量指向要读取的日志缓冲区。list成员变量用来连接其它读者进程。r_off成员变量表示当前要读取的日志在缓冲区中的位置。
struct logger_log结构体中用于保存日志信息的内存缓冲区buffer是一个循环使用的环形缓冲区,缓冲区中保存的内容是以struct logger_entry为单位的,每个单位的组成为:
struct logger_entry | priority | tag | msg
由于是内存缓冲区buffer是一个循环使用的环形缓冲区,给定一个偏移值,它在buffer中的位置由下logger_offset来确定:
#define logger_offset(n) ((n) & (log->size - 1))
|
评论暂时关闭