解读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 LOG机制的实现:(5)获取LOG的应用程序LogCat_第1张图片

一、打开设备节点

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信息。

更多相关文章

  1. 关于Android屏幕刷新机制的一些总结
  2. android 双缓冲机制
  3. Android中Http传递参数json参数请求数据
  4. [Android] [Android的视窗系统及显示机制][上]
  5. Android开发:Handler异步通信机制全面解析(包含Looper、Message Qu
  6. 浅谈Android中的事件分发机制
  7. Android通过JNI实现与C语言的串口通讯操作蓝牙硬件模块
  8. Android群英传--绘图机制与处理技巧(三)

随机推荐

  1. Android(安卓)中一些小经验总结
  2. 【十三】注入框架RoboGuice使用:(Logging
  3. Volley二次封装,实现网络请求缓存
  4. android addJavascriptInterface 不能生
  5. Android不同分辨率的Drawable资源配置
  6. Android下在onCreate方法中获取TextView
  7. Windows下,Ant自动化编译Android项目具体
  8. Android高级的总结
  9. 【Android(安卓)高性能音频】AAudio 音频
  10. Android(安卓)中自定义ContentProvider与