个人免费网站建设模板,免费高清视频软件,自己开个公司做网站,湖北洲天建设集团有限公司网站详细代码实现及系列文章请转如下链接
Android实战经验篇-系列文章汇总 Android Display Graphics系列文章-汇总 一、基础知识
1.1 Logging简述
我们写的第一个计算机C程序一般是printf(“Hello world!”);这就是一个log输出。Linux内核有Kernel log以及配套的Log工具#x…详细代码实现及系列文章请转如下链接
Android实战经验篇-系列文章汇总 Android Display Graphics系列文章-汇总 一、基础知识
1.1 Logging简述
我们写的第一个计算机C程序一般是printf(“Hello world!”);这就是一个log输出。Linux内核有Kernel log以及配套的Log工具Android系统中也设计了一套日志系统方便应用程序的Debug。
Logging由于其简单快捷行之有效并且各种编程语言和操作系统都提供了对Logging的支持以便跟踪程序行为快速定位问题所在所以其一直是调试过程中应用最普遍使用频率最高的手法。
但是一个基于Android系统的手机平台系统的各个部分都有不同的log机制例如Kernel部分沿用了Linux Kernel的Log机制Android部分实现了4个buffer用来分别对Android应用包含Native层的应用和Java层的应用做Logging而搭配的modem则有另外的机制和工具进行Logging。当然除此之外蓝牙网络等等也有自己的机制。
而对应的获取log的工具也是种类繁多的这往往会给大家带来困扰在什么时候用什么样的工具抓取哪些log呢这事关问题处理的效率。
本文将专注于Kernel/Android/Modem各个部分Log机制以及配套工具的使用针对用到的log工具做出简明介绍以让大家了解各个Log工具的使用场景以及应用上的局限性使大家能够在遇到问题的时候准确的拿到对应的Log来做分析。
1.2 Kernel Log
开发Linux device Driver或者跟踪调试内核行为的时候经常要通过Log API来trace整个过程Kernel API printk() 是整个Kernel Log机制的基础API几乎所有的Log方式都是基于printk来实现的。
利用printk我们可以像开发C应用中printf接口一样印log最简单的方式我们只要把需要打印的内容传给printk函数就可以了如下
printk(This is just an example!!);
当然使用printk还有一些需要注意的地方在详细讲述之前我们先分析一下printk()实现其流程大致如下图所示 从上图可以看出printk的流程大致可以分为两步
1、将所有Log输出到内核的Log buffer该Log Buffer是一个循环缓冲区其地址可以在内核中用log_buf变量访问。
2、根据设定的Log级别决定是否将Log输出到Console。 所以我们打印的log会走向两个位置
1、Log Buffer该Buffer的内容可以在user space通过/proc/kmsg来访问。
2、ConsoleConsole的实现可以有很多目前我们用到的有UART Console和RAM Console。拿UART Console来说通向UART Console的log会在对应的UART端口打印出来。而RAM Console也是我们一种重要的Debug手段。 对于console log不可避免的对系统的性能有损失尤其是像UART Log这种收到硬件传输效率影响的。所以对于console log设置了两道关卡。第一个是对Log级别进行过滤只能输出高优先级的log第二个是为UART Console设置单独的开关在不必要的时候可以将其关闭以提高系统性能。
在这里我们提到了Log Level的概念那什么是Log Level呢 LOG 优先级
Log Level也叫做Log优先级为了能够区分各个Log的重要程度printk机制设计了若干Log级别以作区分。当我们读取log buffer adb shell cat /proc/kmsg的时候可以看到如下的log在每一行Log的前面有一对尖角号里面包含一个数字这个数字即为这行Log优先级。
01-01 00:02:59.697 0 0 W kmsg : 4[ 24.512158][ T303] msm-dai-q6-hdmi soc:qcom,msm-dai-q6-dp: DAI driver id is not set
01-01 00:02:59.702 0 0 W kmsg : 4[ 24.513851][ T303] msm-dai-q6-hdmi soc:qcom,msm-dai-q6-dp1: ASoC: sink widget Display Port1 Playback overwritten
01-01 00:02:59.710 0 0 W kmsg : 6[ 24.524825][ C0] CAM_ERR: CAM-CCI: cam_cci_irq: 304 Base:00000000ff02efc8,cci: 1, M0_Q1 NACK ERROR: 0x10000000
01-01 00:02:59.714 0 0 W kmsg : 6[ 24.525221][ T916] CAM_ERR: CAM-CCI: cam_cci_read: 1389
01-01 00:02:59.755 0 0 W kmsg : 6[ 24.570790][ T1117] ipa-wan ipa3_lcl_mdm_ssr_notifier_cb:3037 IPA BEFORE_POWERUP handling is complete
01-01 00:02:59.880 0 0 W kmsg : 3[ 24.681150][ T1126] jack_detect_work_events val 1
01-01 00:02:59.924 0 0 W kmsg : 6[ 24.738219][ T1360] binder: 1360:1360 ioctl 40046210 7fc2d97ef0 returned -22
尖括号中橙色字体就是log的打印等级
完整的8个级别的定义可以参考下表值越小级别越高 宏定义 级别 描述 KERN_EMERG 0 紧急信息此信息会引起系统崩溃 KERN_ALERT 1 提示要马上采取某些行动 KERN_CRIT 2 关键信息通常有严重的软件或者硬件问题发生了 KERN_ERR 3 通常用来报告错误例如设备驱动通常会用来报告硬件操作失败等 KERN_WARNING 4 警告信息用来警告那些并不会造成严重的系统异常的问题 KERN_NOTICE 5 用于正常但是值得注意的情况比如大量安全相关的log KERN_INFO 6 信息许多驱动程序都会在硬件启动的时候使用这个级别打印Log KERN_DEBUG 7 用于调试信息的打印
那优先级是怎么应用的呢
我们可以为将要打印的log指定优先级举例如下可以在我们要打印的log前面简单的添加上Log优先级的宏定义即可这个优先级在printk API里面会去解析处理以判断是否要打印到console中去。
printk(KERN_ERRThis is an error message!!);
如果不指定优先级会怎样呢
如果在印Log的时候不指定Log的优先级printk会为这行Log采用默认的优先级。通常系统默认的优先级是4即warning级别。
系统默认的优先级可以通过读取/proc文件来得到如下所示其中读回来的第2个参数即为未指定Log Level的时候printk默认的Log级别。
E:\adb shell cat /proc/sys/kernel/printk
4 6 1 7
/proc/sys/kernel/printk里面的参数意义是什么
前面我们使用cat读取了/proc/sys/kernel/printk里面的内容读取的这4个数字的含义分别是
1.第一个参数表示console log level即只有优先级大于这个级别的Log才可以打印到Console。
2.第二个参数表示默认Log级别即打印Log未明确指定Log level的时候默认采用的Log级别。
3.第三个参数表示最小可用的Log Level用于do_syslog()系统调用。
4.第四个参数表示默认的Console Log Level未找到使用的地方。
Console Log 输出控制
从前面的图例以及讲述都有提到console_loglevel 决定了哪些级别的log可以输出到console。而console_loglevel的值可以通过 /proc/sys/kernel/printk 来读取出来。
除此之外我们还可以通过/proc/sys/kernel/printk设置console_loglevel来达到控制 console log 输出的目的方法如下修改这个参数需要有root权限
E:\adb shell cat /proc/sys/kernel/printk
4 6 1 7
E:\adb shell echo 8 /proc/sys/kernel/printk
E:\adb shell cat /proc/sys/kernel/printk
8 6 1 7
上面echo 8 一行命令将console_loglevel设置8即所有级别的log因为定义的最低优先级的Log Level是7都可以输出到console。当然通过这个命令也可以禁止一些低优先级的log输出到console只要将console_loglevel的值设置小一些即可。
UART Console 的控制
对于UART Console单独设置了开关主要是因为其对系统性能的影响比较大因为UART Console是同步的方式通过硬件以固定的传输速率印Log如果Log量比较大的时候印Log不可避免会花费系统较多的时间这样就会引起较多的Performance问题如UI卡顿等。另外由于往UART Console印Log会关闭中断严重的时候可能会引起系统无法响应或者重启。
也正因为此我们在user版本上面默认是关闭UART Console Log的。
那么如何在runtime控制UART Console 的打开和关闭呢可以使用如下命令执行该命令需要有root权限
MTK上可以通过如下命令控制
E:\adb shell echo 1 /sys/module/printk/parameters/disable_uart
E:\adb shell echo 0 /sys/module/printk/parameters/disable_uart
通过将disable_uart参数设置为1来关闭UART Console反之通过将disable_uart参数设置为0来打开UART Console。 1.3 Android Log
任何一本讲述Android开发的教科书在讲如何用模拟器调试应用程序的时候都会用到Log类的Java API以及配套工具logcat或者DDMS。这是Android系统里面单独设计的一整套Log机制与Kernel Log机制类似也有优先级 (Priority) 的概念虽然优先级的定义稍有不同。除此之外还对Log添加了对应的TAG以此来对Log的类别作区分。后面我们将详细讲述该Logging机制。
Android Logging System Architecture
Android Logging System对Java层以及Native层都提供了对应的API我们通过下图先看一下Android Logging System整体架构。 从上图我们可以看出
1. 在 Kernel 层设计了4个 Logger 设备及相应的驱动程序这4个 Logger 设备分别采用了一块内存区域作为循环缓冲区用于存放 main/system/event/radio log。详细的实现代码可以参考文件 kernel/drivers/staging/adroid/logger.c
2. 在 Native 层封装了对 kernel log buffer 的写入操作并且在写入前根据传入的TAG决定是否将log写入到 Radio Log Buffer。作为Library向上层提供API。详细的实现可以参考文件夹 system/core/liblog/ 下面的文件。
3. 为了方便 Native 应用程序以及共享库的开发提供了 macro 定义的 Log wrapper这样在 Native 层可以直接使用 LOGV/LOGD/LOGI/LOGW/LOGE 以及相关的 API 打印 Log 到 Log Buffer. 详细的定义以及其他相关的 macro 可以参考文件 system/core/include/log/log.h
4. 为了给 Java层提供接口在 Native 层实现了JNI接口为 Java 层服务。详细的实现可以参考文件夹 frameworks/base/core/jni/ 下面的 android_utils_Log.cpp 和 android_utils_EventLog.cpp 文件。
5. 在 Java 层对 JNI 接口进行了封装分别实现了 android.util.Log 和 android.util.EventLog 类用于给 Java Application 以及 Java library 提供 Log 接口。详细的实现可以参考 frameworks/base/core/java/android/util/ 下面的 Log.java 和 EventLog.java 文件。
API 与优先级
和 Kernel Log 机制类似Android Logging System 也有优先级的概念。相关的优先级定义可以参考下表。 优先级 含义 描述 V Verbose 仅在eng版本中打印在user和userdebug版本都不会打印。最低优先级。 D Debug Debug信息常用于应用程序的调试。 I Information 用于打印通知信息的Log。 W Warning 用于打印警告信息。 E Error 用于打印一般的错误信息。 F Fatal 表示信息会引起致命性的错误。 S Silent 最高优先级主要用于logcat过滤LogS优先级所有Log都不会输出。
优先级的设置有两个用途一是可以利用优先级来揭示Log的重要程度自然越致命的信息越重要。二是Log工具可以根据不同的Log级别来过滤掉不关心的Log。
搭配不同的Log级别就衍生出了各个级别的Log API。
例如在Native层定义了如下的MacroLOGV / LOGD / LOGI / LOGW / LOGE用来打印不同级别的log。此处举例的API并非 Native层定义的所有的API请参考 system/core/include/log/log.h 文件查阅完整的定义
而在Java层的 android.util.Log 类则定义了 Log.v / Log.d / Log.i / Log.w / Log.e 接口用于在Java层打印Log。更完整的API定义请参考文件 frameworks/base/core/java/android/util/Log.java。
1.4 Logging Tools
一个完整的日志系统除了Log保存机制以外还要有Log查看机制。不管是Kernel Log还是Android Log都会将Log打印到buffer那么Log工具则会将Buffer里面的Log拿出来做相应的处理或者打印到终端或者对Log做解析以及过滤等等。而Kernel Log除了打印到buffer以外还会打印到Console那么从console获取Log也是一种常见的方式。
那到底都有哪些Log工具和方法呢常用的Log工具和方法可以参考下表有些可以抓取Kernel Log有些可以抓取Android Log有些则可以同时抓取两种Log。下表列出了各种工具和方法对Android Log和Kernel Log的支持情况以及使用时需要注意的事项。 Android Log Kernel Log NOTE kmsg NO YES 需要adb连接 dmesg NO YES 需要adb连接 UART Log YES YES 需要UART Cable连接 logcat NO YES 需要adb连接 自定义工具 YES YES Kernel logcat log自动存储到指定目录并限定log文件个数和行数
在上面的表格中 kmsg/dmesg 和 UART Log 都是标准Linux Kernel支持的方式。而 logcat/DDMS 是Android提供的标准debug方式。后面我们将详细介绍每一种Log工具。 二、深度解析
2.1 kmsg
在前面 Kernel Log 章节我们有讲过所有的 Kernel Log 都会输出到 Kernel 里面的一个循环的缓冲区 log_buf为了能够方便的在 user space 读取 Kernel logKernel driver 里面将这个 buffer 映射到了 /proc 目录下的文件节点 /proc/kmsg。
所以读取 /proc/kmsg 文件其实就是在访问 Kernel Log 的循环缓冲区。虽然 Log buffe的大小是固定的但是可以通过不断的访问 /proc/kmsg 将所有的log都备份下来。
如下是一个例子我们可以通过 adb shell cat /proc/kmsg 不断的将log打印到shell里面。
除此之外还可以通过重定向将 Log 转存到文件中。例如下面的命令将 kmsg buffer 的内容保存到windows D盘的 kernel_kmsg.log 文件中
D:\ adb shell cat /proc/kmsg d:\kernel_kmsg.log
使用限制
在访问 /proc/kmsg 的时候有一些限制主要是
1、由于 Kernel log buffer 循环缓冲区只有一个读指针所以当一个程序在读 buffer 的时候会不断的移动 buffer 的读指针这样当有多个程序读取 buffer 的时候每个程序得到的log都不是完整的。所以当访问 /proc/kmsg 的时候务必保证没有其它程序读取 Kernel Log Buffer。
2、/proc/kmsg 的 Owner 是 root群组属于 System所以在 user 版本上面是无法通过 adb shell 读取 Kernel Log Buffer 的。安装在手机上的应用也是无法读取这个 buffer 的。
3、如果只是想看看当前 Log Buffer 里面的内容而不是一直录 Log 下去那么请参考下面的章节 “dmesg”。
此方式并不仅仅限于 Android 系统/proc/kmsg 是 Linux 内核标准实现的部分所以任何采用了 Linux 内核的系统都可以用这种方式获取 Kernel Log。 2.2 dmesg
前面 kmsg 的章节讲述了通过 /proc/kmsg 访问 Kernel log buffer 的方式其主要限制是不能有多读者即不能多个程序同时访问 Kernel Log Buffer否则每一个访问程序得到的结果都是不完整的。
但有些时候我们可能并不知道系统里面有哪些后台进程在读取 Kernel Log Buffer这个时候我们如何获取到可信的 Kernel Log呢
系统Android 或者大多数 Linux 发行版里面还有另外一个工具dmesg。dmesg是一个二进制可执行程序我们可以在 adb shell 执行它例如
adb shell dmesg
上述命令会将整个 Log Buffer 从头到尾 dump 到输出设备然后就退出了。它不会操作读指针它只根据写指针把从最旧的 log 到最新的 log 完完整整的输出来。所以这种方式也不会受到其它 Log Buffer 读者的影响。
dmesg 的输出与 /proc/kmsg 的输出是一致的区别是 dmesg dump 完 Kernel Log Buffer 就直接退出了。如下是 dmesg 的输出。
lahaina:/ # dmesg
[ 10.895995] drv_probe, pdata base_mem00000000c6aa4667, mac_regs000000003e07e69a
[ 10.904406] FXGMAC_DRV_NAME:fuxi-gmac, FXGMAC_DRV_VERSION:1.0.21-1122-4
[ 10.911930] read mac from eFuse
[ 10.918469] register desc_ops and hw ops
[ 10.923805] CHIP_RESET 0x80000001
[ 10.938252] check mac regs, get offset 0x110,ver0x1052,mac_regs000000003e07e69a
[ 10.946662] HWFR3: 268435488
[ 10.950349]
[ 10.952610]
[ 10.959600]
[ 10.961862] HW support following features,ver0x1052
[ 10.967689]
[ 10.969962] VLAN Hash Filter Selected : NO
[ 10.976516] SMA (MDIO) Interface : YES
[ 10.983143] PMT Remote Wake-up Packet Enable : YES
[ 10.989772] PMT Magic Packet Enable : YES
[ 10.996397] RMON/MMC Module Enable : YES
[ 11.003020] ARP Offload Enabled : YES
应用场景
dmesg 的使用场景与 /proc/kmsg 的场景是大致相同的同样不适合调试 Kernel BUG当 Kernel 出现 BUG 的时候 dmesg 作为 user space 程序首先就无法正常执行了所以没办法录取到有效的 log 来分析问题。
其适用的场合主要是跟踪调试内核的逻辑或者监测硬件模块的内核行为等等。
dmesg 会完完整整的 dump 一次 Kernel Log Buffer所以不会丢失掉任何的 Log。
使用限制
使用 dmesg 来获取 Kernel Log 也有一些限制如下
1、dmesg 只会一次性 dump Kernel log buffer所以只能得到当下的 log 部分由于 Log buffer 的大小是有限制的在很短的时间内就可能把旧的 Log 覆盖掉所以有可能来不及抓到旧的部分如果 Log 量比较大那么能够抓到的 Log 时间就很短了。所以不适合 Log 量比较大的情况也不适合长时间跟踪内核行为。
2、dmesg 的执行需要有 root 权限才行。所以 Android user 版本是无法使用这个工具的。
3、如果需要长时间录取 Log那就需要访问 /proc/kmsg 的方式。
此方式并不仅仅限于 Android 系统绝大多数的 Linux 发行版都内置了这个应用程序。所以大多数采用 Linux 内核的系统都可以使用此工具。
2.3 UART Log
/proc/kmsg 文件节点映射 Kernel Log Buffer或者 dmesg dump Kernel Log Buffer 实际都是直接从 Buffer 里面获取 Log。在 Kernel Log 章节有讲过所有的 Kernel Log 都会一字不漏的全部写入的 Buffer 中所以通过访问 Log Buffer 的方式获取的 Kernel Log 是最完整的。
在 Kernel Log 章节也有提到 Kernel Log 除了输出到 Buffer 之外还会将一部分 Log 输出的到 Console。所以通过 UART 也是可以获取 Kernel Log的。具体输出哪些 Log 取决于设定的 log level。更详细的信息请参考 Kernel Log 章节。
UART 用于 Logging 是极其广泛的除了 Linux Kernel 默认将其作为 Console 以外系统其它的部分如 bootloader 的 Debug 也和 UART Log 紧密相关。所以 UART Log 对于整个系统的 Debug尤其是开机和关机流程至关重要。
但是 Phone 或者 Tablet 通常都不会留出直接的 UART 接口而只是在电路板上面留出 UART 测试点所以抓取 UART Log 就会相对麻烦一点首先就要准备 UART cable 以及搭建抓取 UART Log 的环境。
2.4 Logcat
Logcat 是 Android SDK 里面提供的命令行下的 Logging 工具用法简单使用方便相关的介绍可以参考 Android Developer 链接: http://developer.android.com/tools/help/logcat.html
用法
命令格式如下在option可以指定一些选项比如输出格式指定 buffer 等而在filter-spec中可以指定过滤规则。
[adb] logcat [option] ... [filter-spec] ...
logcat 可以作为 adb command 来执行利用 target 上面的 adb daemon 来操作 log buffer。
adb logcat -v threadtime
也可以通过 adb 建立的 shell在 shell 里面执行 target 上面的 logcat 程序来操作 log buffer。
adb shell logcat -v threadtime
常用操作
详细的使用方式请参考 Android Developer 上面的介绍这里仅对常用操作进行举例。
1. 如何抓取有效 log
adb logcat -v threadtime main_log.txt
此种方式为最常用的抓取方式会将 log 的 PIDTIDTAG 以及时间戳都打印在一行 log 里面。优先使用此种方式抓取 log一定不要仅仅敲 adb logcat 来抓取 logadb logcat 仅仅会将一些基本的信息打印出来缺少时间戳信息对于分析问题是困难的。
2. 如何仅仅抓取某个 TAG 的 Log
可以使用filter-spec来过滤某一些 logfilter-spec的格式是 TAG:Priority.
adb logcat -v threadtime ActivityManager:D *:S
上面的命令可以仅打印 ActivityManager 等于和高于 debug 级别的log它指定了 ActivityManager 最低 Log 级别为 debug用 * 来匹配其他所有 TAG并将其它所有 TAG 设置为 silent 级别即不输出任何 Log。 三、自定义工具
在实际的项目中把Android系统的kernel log 和logcat log 的输出存储到flash上是非常有用的可以定位问题。实际的生产项目中这一点是必不可少的。
3.1 aplog工具
上面说的logcat工具 可以实现文件的保存并且可以指定保存文件大小和个数。当超出这个设置时自动覆盖。
通过logcat --help查看
$ logcat --help
Usage: logcat [options] [filterspecs]General options:-b, --bufferbuffer Request alternate ring buffer(s):main system radio events crash default allAdditionally, kernel for userdebug and eng builds, andsecurity for Device Owner installations.Multiple -b parameters or comma separated list of buffers areallowed. Buffers are interleaved.Default -b main,system,crash,kernel.-L, --last Dump logs from prior to last reboot from pstore.-c, --clear Clear (flush) the entire log and exit.if -f is specified, clear the specified file and its related rotatedlog files instead.if -L is specified, clear pstore log instead.-d Dump the log and then exit (dont block).--pidpid Only print logs from the given pid.--wrap Sleep for 2 hours or when buffer about to wrap whichevercomes first. Improves efficiency of polling by providingan about-to-wrap wakeup.Formatting:-v, --formatformat Sets log print format verb and adverbs, where format is one of:brief help long process raw tag thread threadtime timeModifying adverbs can be added:color descriptive epoch monotonic printable uid usec UTC year zoneMultiple -v parameters or comma separated list of format and formatmodifiers are allowed.-D, --dividers Print dividers between each log buffer.-B, --binary Output the log in binary.Outfile files:-f, --filefile Log to file instead of stdout.-r, --rotate-kbytesn Rotate log every n kbytes. Requires -f option.-n, --rotate-countcount Sets max number of rotated logs to count, default 4.--idid If the signature id for logging to file changes, then clear theassociated files and continue.Logd control:These options send a control message to the logd daemon on device, print its return message ifapplicable, then exit. They are incompatible with -L, as these attributes do not apply to pstore.-g, --buffer-size Get the size of the ring buffers within logd.-G, --buffer-sizesize Set size of a ring buffer in logd. May suffix with K or M.This can individually control each buffers size with -b.-S, --statistics Output statistics.--pid can be used to provide pid specific stats.-p, --prune Print prune rules. Each rule is specified as UID, UID/PID or /PID. A~ prefix indicates that elements matching the rule should be prunedwith higher priority otherwise theyre pruned with lower priority. Allother pruning activity is oldest first. Special case ~! represents anautomatic pruning for the noisiest UID as determined by the currentstatistics. Special case ~1000/! represents pruning of the worst PIDwithin AID_SYSTEM when AID_SYSTEM is the noisiest UID.-P, --prunelist ... Set prune rules, using same format as listed above. Must be quoted.Filtering:-s Set default filter to silent. Equivalent to filterspec *:S-e, --regexexpr Only print lines where the log message matches expr where expr isan ECMAScript regular expression.-m, --max-countcount Quit after printing count lines. This is meant to be paired with--regex, but will work on its own.--print This option is only applicable when --regex is set and only useful if--max-count is also provided.With --print, logcat will print all messages even if they do notmatch the regex. Logcat will quit after printing the max-count numberof lines that match the regex.-t count Print only the most recent count lines (implies -d).-t time Print the lines since specified time (implies -d).-T count Print only the most recent count lines (does not imply -d).-T time Print the lines since specified time (not imply -d).count is pure numerical, time is MM-DD hh:mm:ss.mmm...YYYY-MM-DD hh:mm:ss.mmm... or sssss.mmm... format.--uiduids Only display log messages from UIDs present in the comma separate listuids. No name look-up is performed, so UIDs must be provided asnumeric values. This option is only useful for the root, log, andsystem users since only those users can view logs from other users.filterspecs are a series oftag[:priority]where tag is a log component tag (or * for all) and priority is:V Verbose (default for tag)D Debug (default for *)I InfoW WarnE ErrorF FatalS Silent (suppress all output)* by itself means *:D and tag by itself means tag:V.
If no * filterspec or -s on command line, all filter defaults to *:V.
eg: *:S tag prints only tag, tag:S suppresses all tag log messages.If not specified on the command line, filterspec is set from ANDROID_LOG_TAGS.If not specified with -v on command line, format is set from ANDROID_PRINTF_LOG
or defaults to threadtime
具体命令如下
/system/bin/logcat -b system -b events -b main -b radio -b crash -v uid -f /data/logs/aplog -r 5000 -n 30
-b system -b events -b main -b radio -b crash 表示选择保存这些模块的log
-v uid 显示uid
-f /data/logs/aplog 存储路径为/data/logs/ 保存文件名为aplog
-r 5000 存储的aplog文件每个5000 kbytes
上述命令会覆盖存储也就是只保存最近的31 x 5000 kbytes 大小的log 3.2 Aplog的selinux策略
上述服务配置放到一个rc文件中即可但需要调试selinux策略这块比较繁琐耗时
关于selinux的详解后边文章介绍。此处文末给出相关patch。 3.3 kernel log工具
前面有说过如果需要长时间录取 Log那就需要访问 /proc/kmsg 。这里自定义实现的Kernel log工具就是访问/proc/kmsg static const char proc_kmsg[] /proc/kmsg;fd android_get_control_file(proc_kmsg);
但需要解决 服务启动后 读取已经缓存到cache的内容和现有内容的衔接。同样也实现和aplog类似功能指定保存最近log的文件个数并且指定文件大小。 例如如下命令
/system/bin/kernel_log -f /data/logs/kernel_kmsg -r 1000 -n 50 -v threadtime -K
-f 指定log路径及文件名
-r 指定每个文件的字节数kbytes
-n 表示文件后缀到 kernel_kmsg.50
-v threadtime 显示格式设置显示线程时间
-K 使能dmesg输出
lahaina:/data/logs# ls aplog* kernel_kmsg*
aplog aplog.12 aplog.24 kernel_kmsg.13 kernel_kmsg.24 kernel_kmsg.35 kernel_kmsg.46
aplog.01 aplog.13 aplog.25 kernel_kmsg.14 kernel_kmsg.25 kernel_kmsg.36 kernel_kmsg.47
aplog.02 aplog.14 aplog.26 kernel_kmsg.15 kernel_kmsg.26 kernel_kmsg.37 kernel_kmsg.48
aplog.03 aplog.15 aplog.27 kernel_kmsg.16 kernel_kmsg.27 kernel_kmsg.38 kernel_kmsg.49
aplog.04 aplog.16 aplog.28 kernel_kmsg.17 kernel_kmsg.28 kernel_kmsg.39 kernel_kmsg.5
aplog.05 aplog.17 aplog.29 kernel_kmsg.18 kernel_kmsg.29 kernel_kmsg.4 kernel_kmsg.50
aplog.06 aplog.18 aplog.30 kernel_kmsg.19 kernel_kmsg.3 kernel_kmsg.40 kernel_kmsg.6
aplog.07 aplog.19 kernel_kmsg kernel_kmsg.2 kernel_kmsg.30 kernel_kmsg.41 kernel_kmsg.7
aplog.08 aplog.20 kernel_kmsg.1 kernel_kmsg.20 kernel_kmsg.31 kernel_kmsg.42 kernel_kmsg.8
aplog.09 aplog.21 kernel_kmsg.10 kernel_kmsg.21 kernel_kmsg.32 kernel_kmsg.43 kernel_kmsg.9
aplog.10 aplog.22 kernel_kmsg.11 kernel_kmsg.22 kernel_kmsg.33 kernel_kmsg.44
aplog.11 aplog.23 kernel_kmsg.12 kernel_kmsg.23 kernel_kmsg.34 kernel_kmsg.45
详细实现见文末代码实现 3.4 Kernel log工具的selinux策略
一般新增的bin工具都新增一个label
此处新增一个 kernel_kmsg
--- /dev/nullb/QSSI.13/device/qcom/sepolicy/testlog/private/file_contexts-0,0 1,2
/data/logs(/.*)? u:object_r:method_trace_data_file:s0
/system/bin/kernel_kmsg u:object_r:kernel_kmsg_exec:s0
所有详细代码实现如下
aplog的selinuxKernel_kmsg源码实现Kernel_kmsg 的selinux实现 见如下链接
Android实战经验篇-系列文章汇总 Android Display Graphics系列文章-汇总