Android Logging System
http://elinux.org/Android_Logging_System
This article describes the Android logging system
Contents[hide]
|
The Android system has a logging facility that allows systemwide logging of information, from applications and system components. This is separate from the Linux kernel's own logging system, which is accessed using 'dmesg' or '/proc/kmsg'. However, the logging system does store messages in kernel buffers.
The logging system consists of:
There are four different log buffers in the Linux kernel, which provide logging for different parts of the system. Access to the different buffers is via device nodes in the file system, in /dev/log.
The four log buffers are:
Up until 2010, only the first three logs existed. The system log was created to keep system messages in a separate buffer (outside of '/dev/log/main') so that a single verbose application couldn't overrun system messages and cause them to be lost.
Each message in the log consists of a tag indicating the part of the system or application that the message came from, a timestamp, the message log level (or priority of the event represented by the message) and the log message itself.
All of the log buffers except for 'event' use free-form text messages. The 'event' buffer is a 'binary' buffer, where the event messages (and event parameters) are stored in binary form. This form is more compact, but requires extra processing when the event is read from the buffer, as well as a message lookup database, to decode the event strings.
The logging system automatically routes messages with specific tags into the radio buffer. Other messages are placed into their respective buffers when the the log class or library for that buffer is used.
The kernel driver for logging is called the 'logger'. See Android logger
An Android application includes the android.util.Log class, and uses methods of this class to write messages of different priority into the log.
Java classes declare their tag statically as a string, which they pass to the log method. The log method used indicates the message "severity" (or log level). Messages can be filtered by tag or priority when the logs are processed by retrieval tools (logcat).
Event logs messages are created using android.util.EventLog class, which create binary-formatted log messages. Log entries consist of binary tag codes, followed by binary parameters. The message tag codes are stored on the system at: /system/etc/event-log-tags. Each message has the string for the log message, as well as codes indicating the values associated with (stored with) that entry.
Many classes in the Android framework utilize the system log to keep their messages separate from (possibly noisy) application log messages. These programs use the android.util.Slog class, with its associated messages.
In all cases, eventually a formatted message is delivered through the C/C++ library down to the kernel driver, which stores the message in the appropriate buffer.
There is a 'log' command line tool that can be used to create log entries from any program. This is built into the 'toolbox' multi-function program.
The usage for this is:
USAGE: log [-p priorityChar] [-t tag] message priorityChar should be one of: v,d,i,w,e
It is sometimes useful to capture stdout from native applications into the log. There is a utility called 'logwrapper' which can be used to run a program, and redirect it's stdout into log messages.
The logwrapper usage is:
Usage: logwrapper [-x] BINARY [ARGS ...] Forks and executes BINARY ARGS, redirecting stdout and stderr to the Android logging system. Tag is set to BINARY, priority is always LOG_INFO. -x: Causes logwrapper to SIGSEGV when BINARY terminates fault address is set to the status of wait()
Source for logwrapper is at: system/core/logwrapper/logwrapper.c
You can use the 'logcat' command to read the log. This command is located in /system/bin in the local filesystem, or you can access the functionality using the 'adb logcat' command.
Documentation on the use of this command is at: http://developer.android.com/guide/developing/tools/adb.html
Some quick notes:
Note that the android logging system is completely separate from the Linux kernel log system (which uses printk inside the kernel to save messages and dmesg to extract them). You can write to the kernel log from user space by writing to /dev/kmsg.
I've seen a reference to couple the two together, to redirect android messages into the kernel log buffer, using the 'logcat' program launched from init, like below:
service logcat /system/bin/logcat -f /dev/kmsg oneshot
(See http://groups.google.com/group/android-kernel/browse_thread/thread/87d929863ce7c29e/f8b0da9ed6376b2f?pli=1)
I'm not sure why you'd want to do this (maybe to put all messages into a single stream? With the same timestamp, if kernel message timestamping is on?)
http://log4think.com/debug-android-logging/
The above image shows the architecture of Android logging system.It provides a java class for logging named android.util.Log. It also provides log macros for native C applications in liblog.
There are four log devices in the kernel.Three for user space log: /dev/log/main, /dev/log/radio, /dev/log/events. One for kernel space log: /dev/log/kernel.
For user space applications, those binary log messages will be written to /dev/log/events. Those log messages with tht tag "HTC_RIL" "RILJ" "RILC" "RILD" "RIL" "AT" "GSM" "STK" will be written to /dev/log/radio. Other log messages will be written to /dev/log/main.
The log devices named /dev/log/kernel is for kernel log message collection. A console is registerred in /dev/log/kernel and collect all the printk output to the device.It will output kernel log messages with the same log format as other log devices.
Logcat is a tool provided by Android.It could read log messages from log devices and output to the console or to a file.You can find the detail usage later.
an aplog daemon is added for offling log.A filter is added to do some security checking.
Class Name: android.util.Log
General method:
Log.v() Log.d() Log.i() Log.w()
The order in terms of verbosity, from least to most is ERROR, WARN, INFO, DEBUG, VERBOSE. Verbose should never be compiled into an application except during development. Debug logs are compiled in but stripped at runtime. Error, warning and info logs are always kept. Tip: A good convention is to declare a TAG constant in your class:
private static final String TAG = "TAG_MyActivity";
and use that in subsequent calls to the log methods.
When you're building the string to pass into Log.d, Java uses a StringBuilder? and at least three allocations occur: the StringBuilder? itself, the buffer, and the String object. Realistically, there is also another buffer allocation and copy, and even more pressure on the gc. That means that if your log message is filtered out, you might be doing significant work and incurring significant overhead.
For more details, please visit http://developer.android.com/reference/android/util/Log.html Android log reference
package com.android.hello; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; import android.util.Log; /*import log class*/ private static final String TAG = "MOT_MyActivity"; /* define log tag*/ public class !HelloAndroid extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* setContentView(R.layout.main); */ Log.i(TAG, "this is a log.i message"); Log.v(TAG, "test is a log.v message"); Log.d(TAG, "test is a log.d message"); Log.w(TAG, "test is a log.w message"); Log.e(TAG, "test is a log.e message"); !TextView tv = new !TextView(this); tv.setText("Hello, Android"); setContentView(tv); } }
Common Logging Macros
LOGV LOGD LOGI LOGW LOGE
The order in terms of verbosity, from least to most is ERROR, WARN, INFO, DEBUG, VERBOSE. Verbose should never be compiled into an application except during development. Debug logs are compiled in but stripped at runtime. Error, warning and info logs are always kept.
Condition Logging Macros
LOGV_IF LOGD_IF LOGI_IF LOGW_IF LOGE_IF
The order in terms of verbosity, from least to most is ERROR, WARN, INFO, DEBUG, VERBOSE. Verbose should never be compiled into an application except during development. Debug logs are compiled in but stripped at runtime. Error, warning and info logs are always kept. The definition is as below:
API for sending log output.
Note:
1: You should define LOG_TAG in your C source code firstly.
2: To build out C/C++ applications outside android, you should add "LOCAL_SHARED_LIBRARIES := liblog libcutils" in your Android.mk file
#include #include /* log header file*/ #include /* define log tag */ #ifdef LOG_TAG #undef LOG_TAG #define LOG_TAG "app" #endif int main() { LOGV( "Verbose: _app"); LOGD( "Debug: _app"); LOGI( "Info: _app"); LOGW( "Warn: _app"); LOGE( "Error: _app"); printf("Hello Android.n"); return 0; }
priorityChar should be one of : v,d,i,w,e
The format of a log messages is
tv_sec tv_nsec priority pid tid tag messageLen Message
tag log tag
tv_sec&tv_nsec the timestamp of the log messages
pid the process id of where log messages come from
tid the thread id
Priority value is one of the following character values, ordered from lowest to highest priority
:
* V — Verbose (lowest priority)*
* D — Debug*
* I — Info*
* W — Warning*
* E — Error*
* F — Fatal*
* S — Silent (highest priority, on which nothing is ever printed)*
Android 软件测试日志文件抓取
1 log文件分类简介
实时打印的主要有:logcat main,logcat radio,logcat events,tcpdump,还有高通平台的还会有QXDM日志
状态信息的有:adb shell cat /proc/kmsg ,adb shell dmesg,adb shell dumpstate,adb shell dumpsys,adb bugreport,工程模式等
2 LOG抓取详解
l 实时打印
adb logcat -b main -v time>app.log 打印应用程序的log
adb logcat -b radio -v time> radio.log 打印射频相关的log,SIM STK也会在里面,modem相关的ATcommand等,当然跟QXDM差的很远了。
adb logcat -b events -v time 打印系统事件的日志,比如触屏事件。。。
tcpdump 是很有用的,对于TCP/IP协议相关的都可以使用这个来抓,adb shell tcpdump -s 10000 -w /sdcard/capture.pcap,比如抓mms下载的时候的UA profile,browser上网的时候,使用proxy的APN下载,streaming的相关内容包括UA profile等。
最后是高通平台的QXDM,不管是不是Android,只要使用高通芯片,都会对它很熟悉,当然了,不是高通的芯片就不用提它了。这个不多讲,内容丰富,射频,电话,上网,...凡是高通提供的解决方案,这个都可以抓。(QXDM 的LOG抓取方法请参考QPST、QXDM的基本使用说明及作用)
l 状态信息
o bugreport(命令adb bugreport>bugreport.log)。里面包含有dmesg,dumpstate和dumpsys。
o dumpstate是系统状态信息,里面比较全,包括手机当前的内存信息、cpu信息、logcat缓存,kernel缓存等等。
o adb shell dumpsys这个是关于系统service的内容都在这个里面,这个命令还有更详尽的用法,比如adb shell dumpsys meminfo system是查看system这个process的内存信息。
o kmsg抓取
adb shell cat /proc/kmsg > kmsg.txt
说明:用于检索用printk生成的内核消息。任何时刻只能有一个具有超级用户权限的进程可以读取这个文件。也可以用系统调用syslog检索这些消息。通常使用工具dmesg或守护进程klogd检索这些消息。proc是一个内存文件系统, 每次读文件kmsg实际是内核内部的循环缓冲区,每读过后,循环缓冲区的东西就被认为已经处理过了(也就是变成无效内容),所以你再次读为空是很正常的 为什么会这样处理呢,循环缓冲区大小有限,内核又随时可能往里面写东西,所以这样处理很正常. 你去查一下/proc/kmsg的信息有没有跟系统日志关联,如果有的话,你就可以读日志文件
o dmsg抓取
adb shell dmesg > dmesg.txt
说明:dmesg用来显示开机信息,kernel会将开机信息存储在ring buffer中。您若是开机时来不及查看信息,可利用dmesg来查看。dmesg是kernel的log,凡是跟kernel相关的,比如driver出了问题(相机,蓝牙,usb,启动,等等)开机信息亦保存在/var/log目录中,名称为dmesg的文件里。more /var/log/dmesg
o 工程模式下log的抓取
对于Apollo手机请拨打*#*#8888#*#* ,然后勾选相应的LOG。待测试结束后,通过SD卡导出LOG到PC.
3.Log分析:
Get Log from Android System
adb bugreport > bugreport.txt
copy bugreport to the current directory.
bugreport里面包含了各种log信息,大部分log也可以通过直接运行相关的程序来直接获得.
步骤如下:
1.adb shell
2.进入相关工具程式的目录
3.执行相关程式
4.得到相关信息
下面以输出进程信息为例
1.adb shell
2.输入ps -P
3.可以看到相关进程信息
Log Archive Analysis
1.bugreport
bugreport记录android启动过程的log,以及启动后的系统状态,包括进程列表,内存信息,VM信息等等到.
2.bugreport结构分析
(1)dumpstate
MEMORY INFO
获取该log:读取文件/proc/meminfo
系统内存使用状态
CPU INFO
获取该log:执行/system/bin/top -n 1 -d 1 -m 30 -t
系统CPU使用状态
PROCRANK
获取该log:执行/system/bin/procrank
执行/system/xbin/procrank后输出的结果,查看一些内存使用状态
VIRTUAL MEMORY STATS
获取该log:读取文件/proc/vmstat
虚拟内存分配情况
vmalloc申请的内存则位于vmalloc_start~vmalloc_end之间,与物理地址没有简单的转换关系,虽然在逻辑上它们也是连续的,但是在物理上它们不要求连续。
VMALLOC INFO
获取该log:读取文件/proc/vmallocinfo
虚拟内存分配情况
SLAB INFO
获取该log:读取文件/proc/slabinfo
SLAB是一种内存分配器.这里输出该分配器的一些信息
ZONEINFO
获取该log:读取文件/proc/zoneinfo
zone info
SYSTEM LOG(需要着重分析)
获取该log:执行/system/bin/logcat -v time -d *:v
会输出在程序中输出的Log,用于分析系统的当前状态
VM TRACES
获取该log:读取文件/data/anr/traces.txt
因为每个程序都是在各自的VM中运行的,这个Log是现实各自VM的一些traces
EVENT LOG TAGS
获取该log:读取文件/etc/event-log-tags
EVENT LOG
获取该log:执行/system/bin/logcat -b events -v time -d *:v
输出一些Event的log
RADIO LOG
获取该log:执行/system/bin/logcat -b radio -v time -d *:v
显示一些无线设备的链接状态,如GSM,PHONE,STK(Satellite Tool Kit)…
NETWORK STATE
获取该log:执行/system/bin/netcfg (得到网络链接状态)
获取该log:读取文件/proc/net/route (得到路由状态)
显示网络链接和路由
SYSTEM PROPERTIES
获取该log:参考代码实现
显示一些系统属性,如Version,Services,network…
KERNEL LOG
获取该log:执行/system/bin/dmesg
显示Android内核输出的Log
KERNEL WAKELOCKS
获取该log:读取文件/proc/wakelocks
内核对一些程式和服务唤醒和休眠的一些记录
KERNEL CPUFREQ
(Linux kernel CPUfreq subsystem) Clock scaling allows you to change the clock speed of the CPUs on the fly.
This is a nice method to save battery power, because the lower the clock speed is, the less power the CPU consumes.
PROCESSES
获取该log:执行ps -P
显示当前进程
PROCESSES AND THREADS
获取该log:执行ps -t -p -P
显示当前进程和线程
LIBRANK
获取该log:执行/system/xbin/librank
剔除不必要的library
BINDER FAILED TRANSACTION LOG
获取该log:读取文件/proc/binder/failed_transaction_log
BINDER TRANSACTION LOG
获取该log:读取文件/proc/binder/transaction_log
BINDER TRANSACTIONS
获取该log:读取文件/proc/binder/transactions
BINDER STATS
获取该log:读取文件/proc/binder/stats
BINDER PROCESS STATE
获取该log:读取文件/proc/binder/proc/*
bind相关的一些状态
FILESYSTEMS
获取该log:执行/system/bin/df
主要文件的一些容量使用状态(cache,sqlite,dev…)
PACKAGE SETTINGS
获取该log:读取文件/data/system/packages.xml
系统中package的一些状态(访问权限,路径…),类似Windows里面的一些lnk文件吧.
PACKAGE UID ERRORS
获取该log:读取文件/data/system/uiderrors.txt
错误信息
KERNEL LAST KMSG LOG
最新kernel message log
LAST RADIO LOG
最新radio log
KERNEL PANIC CONSOLE LOG
KERNEL PANIC THREADS LOG
控制台/线程的一些错误信息log
BACKLIGHTS
获取该log:获取LCD brightness读/sys/class/leds/lcd-backlight/brightness
获取该log:获取Button brightness读/sys/class/leds/button-backlight/brightness
获取该log:获取Keyboard brightness读/sys/class/leds/keyboard-backlight/brightness
获取该log:获取ALS mode读/sys/class/leds/lcd-backlight/als
获取该log:获取LCD driver registers读/sys/class/leds/lcd-backlight/registers
获取相关亮度的一些信息
(2)build.prop
VERSION INFO输出下列信息
当前时间
当前内核版本:可以读取文件(/proc/version)获得
显示当前命令:可以读取文件夹(/proc/cmdline)获得
显示系统build的一些属性:可以读取文件(/system/build.prop)获得
输出系统一些属性
gsm.version.ril-impl
gsm.version.baseband
gsm.imei
gsm.sim.operator.numeric
gsm.operator.alpha
(3)dumpsys
执行/system/bin/dumpsys后可以获得这个log.
经常会发现该log输出不完整,因为代码里面要求该工具最多只执行60ms,可能会导致log无法完全输出来.
可以通过修改时间参数来保证log完全输出.
信息:
Currently running services
DUMP OF SERVICE services-name(running)
Log Code Analysis
Site: .\frameworks\base\cmds\dumpstate\
相关Log程序的代码可以从上面目录获取
Log Analysis Experience
分析步骤
1.查看一些版本信息
确认问题的系统环境
2.查看CPU/MEMORY的使用状况
看是否有内存耗尽,CPU繁忙这样的背景情况出现.
3.分析traces
因为traces是系统出错以后输出的一些线程堆栈信息,可以很快定位到问题出在哪里.
4.分析SYSTEM LOG
系统Log详细输出各种log,可以找出相关log进行逐一分析
实例分析
下面分析我写的一个测试例子,在OnCreate做一个死循环,这样主线程会被锁住,在按下硬件的Back之后会出现ANR的错误.
在traces中发现该程序的堆栈信息如下:
—– pid 20597 at 2010-03-15 01:29:53 —–
Cmd line: com.android.test
DALVIK THREADS:
"main" prio=5 tid=3 TIMED_WAIT
| group="main" sCount=1 dsCount=0 s=N obj=0x2aac6240 self=0xbda8
| sysTid=20597 nice=0 sched=0/0 cgrp=default handle=1877232296
at java.lang.VMThread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:1306)
at java.lang.Thread.sleep(Thread.java:1286)
at android.os.SystemClock.sleep(SystemClock.java:114)
at com.android.test.main.onCreate(main.java:20)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
at android.app.ActivityThread.access$2200(ActivityThread.java:119)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4363)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
"Binder Thread #2" prio=5 tid=11 NATIVE
| group="main" sCount=1 dsCount=0 s=N obj=0x2fb7c260 self=0×143860
| sysTid=20601 nice=0 sched=0/0 cgrp=default handle=1211376
at dalvik.system.NativeStart.run(Native Method)
"Binder Thread #1" prio=5 tid=9 NATIVE
| group="main" sCount=1 dsCount=0 s=N obj=0x2fb7c1a0 self=0x14c980
| sysTid=20600 nice=0 sched=0/0 cgrp=default handle=1207920
at dalvik.system.NativeStart.run(Native Method)
"Signal Catcher" daemon prio=5 tid=7 RUNNABLE
| group="system" sCount=0 dsCount=0 s=N obj=0x2fb7a1e8 self=0x126cc0
| sysTid=20599 nice=0 sched=0/0 cgrp=default handle=1269048
at dalvik.system.NativeStart.run(Native Method)
"HeapWorker" daemon prio=5 tid=5 VMWAIT
| group="system" sCount=1 dsCount=0 s=N obj=0x2e31daf0 self=0x135c08
| sysTid=20598 nice=0 sched=0/0 cgrp=default handle=1268528
at dalvik.system.NativeStart.run(Native Method)
—– end 20597 —–
该文件的堆栈结构从下往上进行分析
(1)栈底at dalvik.system.NativeStart.run(Native Method)
系统为当前的task(应用程式)启动一个专用的虚拟机
(2) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
Activity Services是在后台负责管理Activity,它此时将测试例子的Activity启动起来了
(3)at com.android.test.main.onCreate(main.java:20)
启动测试程序
(4)栈顶at java.lang.VMThread.sleep(Native Method)
线程被sleep掉了,所以无法响应用户,出现ANR错误.
上面是对一个非常简单的问题的分析.
如果遇到比较复杂的问题还需要详细分析SYSTEM LOG.
1.比如网络异常,要通过SYSTEM LOG里面输出的网络链接信息来判断网络状态
2.数据传输,网络链接等耗时的操作需要分析SYSTEM LOG里面ActivityManager的响应时间
3…
让adb logcat打印内核调试信息
http://blog.csdn.net/ryfjx6/article/details/7096018
在默认情况下,adb logcat只能显示应用程序的调试信息,我把logcat.cpp修改了一下,让它同时可以打印内核调试信息:
修改的文件:system/core/logcat/logcat.cpp
1、首先先加入头文件
#include <sys/klog.h> //add by
2、定义所使用的TAG
#define KERNEL_TAG "Kernel"
3、替换readLogLines函数
01.static void readLogLines(log_device_t* devices) 02.{ 03. log_device_t* dev; 04. int max = 0; 05. int ret; 06. int queued_lines = 0; 07. bool sleep = true; 08. char buffer[256] = {0}; //add by zhaofei 09. 10. 11. int result; 12. fd_set readset; 13. 14. 15. for (dev=devices; dev; dev = dev->next) { 16. if (dev->fd > max) { 17. max = dev->fd; 18. } 19. } 20. 21. 22. while (1) { 23. do { 24. timeval timeout = { 0, 5000 /* 5ms */ }; // If we oversleep it's ok, i.e. ignore EINTR. 25. FD_ZERO(&readset); 26. for (dev=devices; dev; dev = dev->next) { 27. FD_SET(dev->fd, &readset); 28. } 29. result = select(max + 1, &readset, NULL, NULL, sleep ? NULL : &timeout); 30. } while (result == -1 && errno == EINTR); 31. 32. 33. if (result >= 0) { 34. for (dev=devices; dev; dev = dev->next) { 35. if (FD_ISSET(dev->fd, &readset)) { 36. queued_entry_t* entry = new queued_entry_t(); 37. /* NOTE: driver guarantees we read exactly one full entry */ 38. ret = read(dev->fd, entry->buf, LOGGER_ENTRY_MAX_LEN); 39. if (ret < 0) { 40. if (errno == EINTR) { 41. delete entry; 42. goto next; 43. } 44. if (errno == EAGAIN) { 45. delete entry; 46. break; 47. } 48. perror("logcat read"); 49. exit(EXIT_FAILURE); 50. } 51. else if (!ret) { 52. fprintf(stderr, "read: Unexpected EOF!\n"); 53. exit(EXIT_FAILURE); 54. } 55. 56. 57. entry->entry.msg[entry->entry.len] = '\0'; 58. 59. 60. dev->enqueue(entry); 61. ++queued_lines; 62. 63. 64.#if 1 //read kernel log 65. if((ret = klogctl(9, buffer, sizeof(buffer))) > 0) { 66. if((ret = klogctl(2, buffer, sizeof(buffer))) > 0) { 67. entry->entry.tid = 0; 68. entry->entry.pid = getpid(); 69. /*priority*/ 70. entry->entry.msg[0] = ANDROID_LOG_INFO; 71. /*tag*/ 72. strcpy(entry->entry.msg+1, KERNEL_TAG); 73. /*message*/ 74. strncpy(entry->entry.msg+1+sizeof(KERNEL_TAG), buffer, ret); 75. entry->entry.len = 1 + sizeof(KERNEL_TAG) + ret + 1; 76. entry->entry.msg[entry->entry.len] = '/0'; 77. /* 78. if (g_printBinary) { 79. printBinary(dev, entry->entry); 80. } else { 81. (void) processBuffer(dev, entry->entry); 82. } 83. */ 84. printNextEntry(dev); 85. } 86. } 87.#endif 88. } 89. } 90. 91. 92. if (result == 0) { 93. // we did our short timeout trick and there's nothing new 94. // print everything we have and wait for more data 95. sleep = true; 96. while (true) { 97. chooseFirst(devices, &dev); 98. if (dev == NULL) { 99. break; 100. } 101. if (g_tail_lines == 0 || queued_lines <= g_tail_lines) { 102. printNextEntry(dev); 103. } else { 104. skipNextEntry(dev); 105. } 106. --queued_lines; 107. } 108. 109. 110. // the caller requested to just dump the log and exit 111. if (g_nonblock) { 112. exit(0); 113. } 114. } else { 115. // print all that aren't the last in their list 116. sleep = false; 117. while (g_tail_lines == 0 || queued_lines > g_tail_lines) { 118. chooseFirst(devices, &dev); 119. if (dev == NULL || dev->queue->next == NULL) { 120. break; 121. } 122. if (g_tail_lines == 0) { 123. printNextEntry(dev); 124. } else { 125. skipNextEntry(dev); 126. } 127. --queued_lines; 128. } 129. } 130. } 131.next: 132. ; 133. } 134.}
这里没有把内核调试信息的级别转换成Androind的LOG级别,entry->entry.msg[0] = Android_LOG_INFO;使用了ANDROID_LOG_INFO级别,进程ID用了当前的进程ID。
然后就可以使用logcat来抓取kernel的log了!