解读Android LOG机制的实现:(5)获取LOG的应用程序LogCat

2024-04-01 04:08

本文主要是介绍解读Android LOG机制的实现:(5)获取LOG的应用程序LogCat,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

解读Android LOG机制的实现:(5)获取LOG的应用程序LogCat

田海立@CSDN

2011/07/27

 

Android提供的LOG机制的实现贯穿了Java,JNI,本地c/c++实现以及LINUX内核驱动等Android的各个层次,并且简单明晰,是一个相当不错的解读案例。本系列文章针对LOG机制的内部实现机理进行解读,本文是本系列的第五篇,解读应用程序LogCat如何通过对设备文件的open()/select()/read()来获取LOG信息。

 

从前文知道,LOG被写入到了驱动的节点,那如何获取这些LOG信息并呈现出来的呢?ANDROID里是有个叫LogCat的应用程序被用来获取LOG信息。LogCat不仅从设备节点处获取LOG,并且还提供了很多选项供用户来过滤、控制输出格式等。本文只讲解如何获取LOG部分,相关的LogCat的使用方式,可参考Android的Logcat命令详解。

LogCat是在文件system/core/logcat/logcat.cpp中实现的。

从Logger设备驱动的实现知道,Log的读取是阻塞的操作,亦即,有数据可用,读出数据;否则,读操作会被BLOCK,相应的读进程也会被挂起等待。下面看应用程序LogCat中如何实现读的,这可能需要不断回头与写操作和驱动实现结合来看。

看具体实现之前,先看一个logcat中定义的重要的结构体log_device_t。其中的重要的成员在后面用到的时候再具体解释。

 

 

一、打开设备节点

Android的Logcat命令详解的命令参数-b <buffer>知道,logcat是可以通过参数来指定对哪个buffer(main/radio/event)进行操作的。Logcat的b参数解析的地方,是通过传递进来的参数(main/radio/event)来创建了一个上面的结构变量,而这些结构通过log_device_t.next链接起来。

                if (devices) {dev = devices;while (dev->next) {dev = dev->next;}dev->next = new log_device_t(buf, binary, optarg[0]);} else {devices = new log_device_t(buf, binary, optarg[0]);}

 

而创建实例的时候的参数被保留了下来,用于后续操作。

<buf>是由LOG_FILE_DIR和optarg(-b参数)组合在一起的(为:“/dev/log/main”,“/dev/log/event”或“/dev/log/radio”),保留在device: char*;

<binary>保留在binary: bool;

<optarg[0]>是-b参数的第一个字符,保存在label: char中。

好了,下面就有了打开设备节点时的参数:

dev->fd = open(dev->device, mode);

dev->device根据-b的参数可能为“/dev/log/main”,“/dev/log/event”或“/dev/log/radio”;

mode缺省时为O_RDONLY,读取。只要在运行logcat时,用了-c参数清除log时才以O_WRONLY打开。

而打开文件的文件操作符保存在log_device_t的fd域中,用于后续的操作。

 

获取Log的操作都是在readLogLines(log_device_t* devices)中实现的。

 

因为logcat可能会同时操作多个Buffer,而read()会阻塞读取进程,对其他Buffer的读取就不能进行,所以这里用select()来判断可读取的Buffer。

二、select选取可读取的Buffer

Logcat把log_device_t中的所有的buffer的文件操作符dev->fd,都放在readset中[line#7],做为select()的里的<readfds: fd_set*>读参数,来获取可读取的Buffer。这样当任何一个Buffer上有LOG数据时,select()都会返回。当然等待过程中也忽略掉其他signal的影响。相应的代码如下:

       fd_set readset; do {timeval timeout = { 0, 5000 /* 5ms */ }; // If we oversleep it's ok, i.e. ignore EINTR.FD_ZERO(&readset);for (dev=devices; dev; dev = dev->next) {FD_SET(dev->fd, &readset);}result = select(max + 1, &readset, NULL, NULL, sleep ? NULL : &timeout);} while (result == -1 && errno == EINTR);

 

三、读LOG操作

select()返回之后,通过循环判定dev->fd是否在readset里被设置(FD_ISSET)[line#3],知道哪个log buffer里已经有数据了。

        if (result >= 0) {for (dev=devices; dev; dev = dev->next) {if (FD_ISSET(dev->fd, &readset)) {queued_entry_t* entry = new queued_entry_t();/* NOTE: driver guarantees we read exactly one full entry */ret = read(dev->fd, entry->buf, LOGGER_ENTRY_MAX_LEN);//…

 

通过read()读取[line#6]已经有数据的LOG Buffer的文件操作符dev->fd就可得到新到来的log了。

 

应用程序logcat中已经获取了LOG信息,接下来对数据的处理就都可以在这里进行了,可以过滤,写文件,格式化输入等操作。详细的logcat的命令参数可参见Android的Logcat命令详解。

 

【本系列文章】

解读Android LOG机制的实现:(1)LOG的实现架构

        解读LOG机制的实现架构。

解读Android LOG机制的实现:(2)Java域输出LOG

        解读Android的Java程序中如何输出LOG信息到LOG的体系中。

解读Android LOG机制的实现:(3)JNI及NATIVE域写设备文件

        解读android.util.Log的JNI实现,以及在c/c++的本地实现中如何操作设备文件写Log信息。

解读Android LOG机制的实现:(4)LOG设备驱动logger

        解读LINUX内核中的设备驱动Logger中实现。Logger是Android为Linux写的一个MISC类型驱动,用循环队列实现了读者/写者。Logger是整个LOG机制实现的核心。

解读Android LOG机制的实现:(5)获取LOG程序LogCat

        解读应用程序LogCat如何通过对设备文件的open()/select()/read()来获取LOG信息。

解读Android LOG机制的实现:(6)c/c++域使用LOG

        解读Android的c/c++程序中如何使用LOG机制记录LOG信息。

 

这篇关于解读Android LOG机制的实现:(5)获取LOG的应用程序LogCat的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/866168

相关文章

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

MySQL中的锁机制详解之全局锁,表级锁,行级锁

《MySQL中的锁机制详解之全局锁,表级锁,行级锁》MySQL锁机制通过全局、表级、行级锁控制并发,保障数据一致性与隔离性,全局锁适用于全库备份,表级锁适合读多写少场景,行级锁(InnoDB)实现高并... 目录一、锁机制基础:从并发问题到锁分类1.1 并发访问的三大问题1.2 锁的核心作用1.3 锁粒度分

java实现docker镜像上传到harbor仓库的方式

《java实现docker镜像上传到harbor仓库的方式》:本文主要介绍java实现docker镜像上传到harbor仓库的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 前 言2. 编写工具类2.1 引入依赖包2.2 使用当前服务器的docker环境推送镜像2.2

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Java easyExcel实现导入多sheet的Excel

《JavaeasyExcel实现导入多sheet的Excel》这篇文章主要为大家详细介绍了如何使用JavaeasyExcel实现导入多sheet的Excel,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录1.官网2.Excel样式3.代码1.官网easyExcel官网2.Excel样式3.代码

python实现对数据公钥加密与私钥解密

《python实现对数据公钥加密与私钥解密》这篇文章主要为大家详细介绍了如何使用python实现对数据公钥加密与私钥解密,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录公钥私钥的生成使用公钥加密使用私钥解密公钥私钥的生成这一部分,使用python生成公钥与私钥,然后保存在两个文

MySQL之InnoDB存储页的独立表空间解读

《MySQL之InnoDB存储页的独立表空间解读》:本文主要介绍MySQL之InnoDB存储页的独立表空间,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、独立表空间【1】表空间大小【2】区【3】组【4】段【5】区的类型【6】XDES Entry区结构【

浏览器插件cursor实现自动注册、续杯的详细过程

《浏览器插件cursor实现自动注册、续杯的详细过程》Cursor简易注册助手脚本通过自动化邮箱填写和验证码获取流程,大大简化了Cursor的注册过程,它不仅提高了注册效率,还通过友好的用户界面和详细... 目录前言功能概述使用方法安装脚本使用流程邮箱输入页面验证码页面实战演示技术实现核心功能实现1. 随机