Android 日志系统--01:logd、logcat入门篇

2023-12-13  本文已影响0人  DarcyZhou

本文转载自:Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性

本文基于Android 10.0源码分析

1.概述

  在程序开发中,日志是必不可少的一个调试手段,Android的开发亦是如此。在Android的开发中,我们是通过LOGD\SLOGD等方式进行日志的写入,然后通过logcat读取相关的日志,但是日志是如何写入和读取的,底层的操作是什么,有时候没有深入研究。

  在Android 5.0之前,log由kernel的环形buffer保存,在Android 5.0之后,log保存在用户空间,通过Socket进行访问。在Android 5.0之后,引入了Logd的守护进程用来进行日志的读写操作。早期的Kernel ring buffer的原理可以参考罗升阳的《Android日志系统驱动程序Logger源代码分析》。

  本节主要来分析logd、logcat的相关实现原理。

2.核心源码

/frameworks/base/core/java/android/util/Log.java
/frameworks/base/core/java/android/util/SLog.java
/frameworks/base/core/java/android/util/EventLog.java
/frameworks/base/core/jni/android_util_Log.cpp
/system/core/logd/main.cpp
/system/core/logd/LogReader.cpp
/system/core/logd/LogWriter.java
/system/core/logcat/logcat.cpp
/system/core/liblog/logd_writer.cpp
/system/core/liblog/logd_reader.cpp

3.logcat指令说明

  手机连上电脑,安装adb驱动后,打开开发者模式,选择"USB调试",即可执行adb命令。

3.1 命令行语法

  要通过adb shell运行Logcat,一般用法如下:

[adb] logcat [<option>] ... [<filter-spec>] ...

3.2 指令说明

  可以通过 "adb logcat --help" 来看logcat支持的指令。详细信息参考《Logcat 命令行工具》。

日志系统1-1.png

3.3 日志过滤输出

  Android日志分为如下7个等级:

(1)在调试日志时,可以根据不同的等级来控制日志的输出,下面这是一条正常输出的Android日志

(2)可以通过过滤器只输出相应等级以下的日志:

3.4 日志输出格式

  除标记和优先级外,日志消息还包含许多元数据字段。可以修改消息的输出格式,以便它们显示特定的元数据字段。为此,可以使用-v选项,并指定下列某一受支持的输出格式。

(1)指令: [adb] logcat [-v <format>];
(2)例如:adb logcat -v threadtime;
(3)注意:-v每次只能使用一种格式,默认情况下的threadtime格式即能满足我们现在的需求。

3.5 日志缓冲区

  Android 日志记录系统为日志消息保留了多个环形缓冲区,而且并非所有的日志消息都会发送到默认的环形缓冲区。要查看其他日志消息,可以使用-b选项运行logcat命令,以请求查看备用的环形缓冲区。可以查看下列任意备用缓冲区:

(1)用法1:adb logcat -b main
(2)说明1:上述指令只输出main缓冲区的日志。
(3)用法2:adb logcat -b main,radio,system
(4)说明2:上述指令输出 main、radio、system三个缓冲区的日志。

4.日志系统相关属性说明

属性 说明
log.tag.* setprop log.tag.MyApp D 用来设置应用日志TAG的等级,上面是输出MyApp的Debug日志,主要控制的是isLoggable(MyApp,Debug) 这种方式控制的日志,手动设置后,重启失效
ro.logd.auditd 启动selinux审核守护进程
ro.logd.auditd.dmesg selinux审核信息发送到dmesg log
ro.logd.kernel cat “/proc/kmsg” 节点,用来读取kernel日志
ro.logd.size 所有日志缓存区大小的默认大小,默认为256K,可实时修改,重启失效
ro.logd.timestamp 修改日志时间戳,可以实时修改,重启失效
ro.logd.filter 日志黑白名单是否生效,disable为失效,enable为生效
logd.statistics 使能logcat -S statistics,在输出中包含统计信息,以帮助您识别和定位日志垃圾信息发送者
persist.logd.timestamp 修改日志时间戳,只能编译版本的时候修改,或者手机root后修改,重启继续生效
persist.logd.size 所有日志缓存区大小的默认大小,默认为256K只能编译版本的时候修改,或者手机root后修改,重启继续生效
persist.logd.size.main main日志缓冲区大小,默认为256K
persist.logd.size.system system日志缓冲区大小,默认为256K
persist.logd.filter 日志黑白名单是否生效,disable为失效,enable为生效,通过adb logcat -p 来读取黑白名单;通过logcat -P '<white_and_blacklist>' 来设置黑白名单,通过PID\UID来进行控制
persist.log.tag setprop persist.log.tag Debug控制Debug以上等级的日志输出,只有在版本预制,或者root后,设置生效,重启也生效
ro.logd.kernel setprop ro.logd.kernel true控制内核日志输出到logd的buffer中,通过lgocat抓取
ro.logd.auditd setprop ro.logd.auditd true控制selinux日志输出到logd的buffer中,通过lgocat抓取

  在日常调试或者CTS测试时,会遇到日志丢失或者不全的情况,主要原因是日志量很大,但是日志缓冲区很小,此时只要把日志的缓冲区调大即可。

5.日志分类

  Android 10.0上日志分为8类:

ID 对应值 说明
LOG_ID_MAIN 0 main日志缓冲区,这是应用程序唯一可用的日志缓冲区,在应用框架层提供了android.util.Log接口通过liblog库来往Logger日志驱动程序中写入日志,在运行时库提供了宏LOGV、LOGD、LOGI、LOGW、LOGE用来写入main类型的日志。
LOG_ID_RADIO 1 查看包含无线装置/电话相关消息的日志,可以调用android.telephony.Rlog进行打印
LOG_ID_EVENTS 2 类型为events的日志是用来诊断系统问题的,在应用框架层提供了android.util.EventLog接口通过liblog库来往Logger日志驱动程序中写入日志,在运行时库提供了宏LOG_EVENT_INT、LOG_EVENT_LONG、LOG_STRING用来写入event类型的日志。
LOG_ID_SYSTEM 3 类型为system的日志是系统级别的,在应用框架层提供了android.util.SLog接口通过liblog库来往Logger日志驱动程序中写入日志,在运行时库提供了宏SLOGV、SLOGD、SLOGI、SLOGW、SLOGE用来写入system类型的日志。
LOG_ID_CRASH 4 应用或者进程crash日志缓冲区
LOG_ID_STATS 5 统计日志缓冲区
LOG_ID_SECURITY 6 安全日志缓冲区
LOG_ID_KERNEL 7 kernel日志缓冲

常用的日志缓冲区为:main、radio、system、events、crash,另外内核的日志,主要是输出到/proc/kmsg,通过 cat /proc/kmsg 获取内核日志。

上一篇 下一篇

猜你喜欢

热点阅读