Android Logging System

Android Logging System

http://elinux.org/Android_Logging_System

This article describes the Android logging system

Contents

 [hide] 
  • 1 Overview
  • 2 Kernel driver
  • 3 System and Application logging
    • 3.1 Application log
    • 3.2 Event log
    • 3.3 System log
  • 4 'log' command line tool
  • 5 Capturing stdout with logwrapper
  • 6 Logcat command
    • 6.1 Trick to couple Android logging to Linux kernel logging
  • 7 Resources

Overview

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.

Android Logging System_第1张图片
image by Tetsuyuki Kobabayshi, of Kyoto Microcomputer Co.

The logging system consists of:

  • a kernel driver and kernel buffers for storing log messages
  • C, C++ and Java classes for making log entries and for accessing the log messages
  • a standalone program for viewing log messages (logcat)
  • ability to view and filter the log messages from the host machine (via eclipse or ddms)

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:

  • main - the main application log
  • events - for system event information
  • radio - for radio and phone-related informatio
  • system - a log for low-level system messages and debugging

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.

Kernel driver

The kernel driver for logging is called the 'logger'. See Android logger

System and Application logging

Application log

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 log

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.

System log

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.

'log' command line tool

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

Capturing stdout with logwrapper

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

Logcat command

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:

  • Log messages each have a tag and priority.
    • You can filter the messages by tag and log level, with a different level per tag.
  • You can specify (using a system property) that various programs emit their stdout or stderr to the log.

Trick to couple Android logging to Linux kernel logging

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?)

Resources

  • Android Debug Bridge reference page - has 'adb logcat' usage information
  • Logging System Of Android Presentation by Tetsuyuki Kobayashi, September, 2010 at CELF's Japan Technical Jamboree 34

How to debug with Android Logging

http://log4think.com/debug-android-logging/

AP Logger Architecture

Android Logging System_第2张图片

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.

Logging interface For Java applications

Logging class Introduction

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.

 Log.v(TAG, "index=" + i);

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

Program Example

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);
 }
}

Logging interface For Native applications

Header File

 #include <cutils/log.h>

Logging Macros

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:

#define CONDITION(cond) (__builtin_expect((cond)!=0,0))
#define LOGV_IF(cond, ...)   ( (CONDITION(cond)) ?((void)LOG(LOG_VERBOSE, LOG_TAG, VA_ARGS)) : (void)0 )

Logging Macros overview

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

Program Example

#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;
}

Log command on Android

Command location

 /system/bin/log

Command usage

 log [-p priorityChar] [-t tag] message

priorityChar should be one of : v,d,i,w,e

Log format on Android

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了!

你可能感兴趣的:(android,logging)