Logger详解(一)
16lz
2021-01-23
本文编辑整理自: http://www.linuxidc.com/Linux/2011-07/38987.htm 一、简介 Android为我们提供了一个轻量级的日志系统,在用户空间分别提供了Java接口和C/C++接口来使用这个日志系统。 关于Android的日志系统,请先阅读《 Android中LOG机制详解》,《 在Android的c/c++域使用LOG》,《 logcat命令详解》 Android日志系统最终还是以驱动程序的形式实现在内核空间的。Logger驱动程序主要由两个文件构成,分别是: kernel/common/drivers/staging/Android/logger.h kernel/common/drivers/staging/Android/logger.c 本文将介绍Logger驱动程序的相关数据结构,然后对Logger驱动程序源代码进行情景分析,分别日志系统初始化情景、日志读取情景和日志写入情景。 二、基本数据结构 我们首先来看logger.h头文件的内容: #ifndef _LINUX_LOGGER_H #define _LINUX_LOGGER_H #include #include 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_SYSTEM "log_SYSTEM" /* system/framework message*/ #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 */ logger_entry 是一个用于描述一条 Log 记录的结构体。 len 成员变量记录了这 条记录的有效负载的长度,有效负载指定的日志记录本身的长度,但是不包括用于描述这个记录的 struct logger_entry 结构体 。我们调用Android.util.Log接口来使用日志系统时,会指定日志的优先级别Priority、Tag字符串以及Msg字符串;Priority + Tag + Msg三者内容的长度加起来就是记录的有效负载长度了。 __pad 成员变量是用来对齐结构体的。 pid 和 tid 成员变量分别用来标明是 哪条进程 , 哪个线程 写入的这条记录。 sec 和 nsec 成员变量记录日志写的时间。 msg 成员变量记录的就有效负载的内容了,它的大小由 len 成员变量来确定。 接着定义两个宏: #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))
结构体 logger_log 就是真正用来保存日志的地方了。 buffer 成员变量变是用保存日志信息的内存缓冲区,它的大小由 size 成员变量确定。从 misc 成员变量可以看出, logger驱动程序使用的设备属于misc类型的设备,通过在Android模拟器上执行cat /proc/devices命令,可以看出,misc类型设备的 主设备号是10 。 wq 成员变量是 一个等待队列,用于保存正在等待读取日志的进程 。 readers 成员变量用来保存当前正在读取日志的进程,正在读取日志的进程由结构体 logger_reader 来描述。 mutex 成员变量是一个互斥量,用来保护log的并发访问。可以看出, 这里的日志系统的读写问题,其实是一个生产者-消费者的问题,因此,需要互斥量来保护log的并发访问 。 w_off 成员变量 用来记录下一条日志应该从哪里开始写 。 head 成员变量用来表示打开日志文件中,应该从哪一个位置开始读取日志。 结构体 logger_reader 用来表示一个读取日志的进程, log 成员变量指向要读取的日志缓冲区。 list 成员变量用来连接其它读者进程。 r_off 成员变量 表示当前要读取的日志在缓冲区中的位置 。 logger_log 结构体中用于保存日志信息的内存缓冲区 buffer 是一个循环使用的环形缓冲区,缓冲区中保存的内容是以结构体 logger_entry 为单位的,每个单位的组成为: logger_entry + priority + tag + msg 由于是内存缓冲区buffer是一个循环使用的环形缓冲区,给定一个偏移值,它在buffer中的位置由下logger_offset来确定: #define logger_offset(n) ((n) & (log->size - 1))
结构体 logger_log 就是真正用来保存日志的地方了。 buffer 成员变量变是用保存日志信息的内存缓冲区,它的大小由 size 成员变量确定。从 misc 成员变量可以看出, logger驱动程序使用的设备属于misc类型的设备,通过在Android模拟器上执行cat /proc/devices命令,可以看出,misc类型设备的 主设备号是10 。 wq 成员变量是 一个等待队列,用于保存正在等待读取日志的进程 。 readers 成员变量用来保存当前正在读取日志的进程,正在读取日志的进程由结构体 logger_reader 来描述。 mutex 成员变量是一个互斥量,用来保护log的并发访问。可以看出, 这里的日志系统的读写问题,其实是一个生产者-消费者的问题,因此,需要互斥量来保护log的并发访问 。 w_off 成员变量 用来记录下一条日志应该从哪里开始写 。 head 成员变量用来表示打开日志文件中,应该从哪一个位置开始读取日志。 结构体 logger_reader 用来表示一个读取日志的进程, log 成员变量指向要读取的日志缓冲区。 list 成员变量用来连接其它读者进程。 r_off 成员变量 表示当前要读取的日志在缓冲区中的位置 。 logger_log 结构体中用于保存日志信息的内存缓冲区 buffer 是一个循环使用的环形缓冲区,缓冲区中保存的内容是以结构体 logger_entry 为单位的,每个单位的组成为: logger_entry + priority + tag + msg 由于是内存缓冲区buffer是一个循环使用的环形缓冲区,给定一个偏移值,它在buffer中的位置由下logger_offset来确定: #define logger_offset(n) ((n) & (log->size - 1))
更多相关文章
- android 使用Intent传递数据之全局变量传递
- android环境变量的设置及注意问题
- Android环境变量
- 如何配置android的adb环境变量
- Android环境变量配置
- Android 配置环境变量
- android环境变量设置以及adb的常用命令
- JAVA & Android 系统环境变量配置