在前面两篇文章Android 日志系统驱动程序Logger 源代码分析和Android 应用程序框架层和系统运行库层日志系统源代码中,介绍了Android 内核空间层、系统运行库层和应用程序框架层日志系统相关的源代码,其中,后一篇文章着重介绍了日志的写入操作。为了描述完整性,这篇文章着重介绍日志的读取操作,这就是我们在开发 Android 应用程序时,经常要用到日志查看工具 Logcat 了。 Logcat 工具内置在Android 系统中,可以在主机上通过 adb logcat 命令来查看模拟机上日志信息。Logcat 工具的用法很丰富,因此,源代码也比较多,本文并不打算完整地介绍整个Logcat 工具的源代码,主要是介绍Logcat 读取日志的主线,即从打开日志设备文件到读取日志设备文件的日志记录到输出日志记录的主要过程,希望能起到一个抛砖引玉的作用。 Logcat 工具源代码位于 system/core/logcat 目录下,只有一个源代码文件logcat.cpp,编译后生成的可执行文件位于 out/target/product/generic/system/bin 目录下,在模拟机中,可以在/system/bin 目录下看到 logcat 工具。下面我们就分段来阅读 logcat.cpp 源代码文件。 一. Logcat 工具的相关数据结构。 这些数据结构是用来保存从日志设备文件读出来的日志记录: view plain 1. struct queued_entry_t { 2. union { 3. unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4))); 4. struct logger_entry entry __attribute__((aligned(4))); 5. }; 6. queued_entry_t* next; 7. 8. queued_entry_t() { 9. next = NULL; 10. } 11. }; 12. 13. struct log_device_t { 14. char* device; 15. bool binary; 16. int fd; 17. bool printed; 18. char label; 19. 20. queued_entry_t* queue; 21. log_device_t* next; 22. 23. log_device_t(char* d, bool b, char l) { 24. device = d; 25. binary = b; 26. label = l; 27. queue = NULL; 28. next = NULL; 29. printed = false; 30. } 31. 32. void enqueue(queued_entry_t* entry) { 33. if (this->queue == NULL) { 34. this->queue = entry; 35. } else { 36. queued_entry_t** e = &this->queue; 37. while (*e && cmp(entry, *e) >= 0) { 38. e = &((*e)->next); 39. } 40...