android日志系统详解

您所在的位置:网站首页 建立debug调试日志 android日志系统详解

android日志系统详解

2023-05-19 11:04| 来源: 网络整理| 查看: 265

目录

一,背景介绍

二,基础概念

2.1 日志等级

2.2 日志缓冲区

2.3 调整Android log buffer 大小

三,实现原理

3.1 日志架构

3.2 调用流程

3.2.1 写流程

3.2.2 读流程

四,源码分析

4.1 logd守护进程启动

4.2 启动 logd-reinit

4.3 启动 logd-auditctl

4.4 logcat启动

一,背景介绍

        在framework开发过程中,日志是必不可少的一个调试手段。Android通过LOGD、SLOGD和EventLog等方式进行日志的打点。但是日志是如何写入和读取的?开启android日志系统之旅。

二,基础概念 2.1 日志等级 Android日志分为如下7个等级: V:详细(最低优先级)--(Verbose:2) D:调试 --(Debug:3) I :信息 -- (Info:4) W:警告 --(Warning:5) E:错误 --(Error:6) F:严重错误 --(Fatal:7) S:静默(最高优先级,绝不会输出任何内容)--(Silent)

 下面这是一条正常输出的Android11日志:    

日志内容:2023-05-08 10:48:30.111 21802-21838 AutofillManagerService system_process D onBackKeyPressed() 日志格式: -

2.2 日志缓冲区

        Android 日志系统为日志消息保留了多个缓冲区,可以通过 -b 参数指定特定的缓冲区日志,常用缓存区如下:

    radio:查看包含无线装置/电话相关消息的缓冲区。

    events:查看已经过解译的二进制系统事件缓冲区消息。

    main:查看主日志缓冲区(默认),不包含系统和崩溃日志消息。

    system:查看系统日志缓冲区(默认)。

    crash:查看崩溃日志缓冲区(默认)。

    all:查看所有缓冲区。

    default:报告 main、system 和 crash 缓冲区。

$ adb logcat -b events 05-08 10:48:30.199 29284 29284 I wm_on_start_called: [193592054,com.android.launcher3.uioverrides.QuickstepLauncher,handleStartActivity] 05-08 10:48:30.201 29284 29284 I wm_on_resume_called: [193592054,com.android.launcher3.uioverrides.QuickstepLauncher,RESUME_ACTIVITY] 05-08 10:48:30.201 29284 29284 I wm_on_top_resumed_gained_called: [193592054,com.android.launcher3.uioverrides.QuickstepLauncher,topWhenResuming] 05-08 10:48:30.886 21802 21840 I wm_destroy_activity: [0,185499341,49,com.android.settings/.Settings,finish-imm:idle] 05-08 10:48:30.918 6828 6828 I wm_on_stop_called: [185499341,com.android.settings.Settings,LIFECYCLER_STOP_ACTIVITY] 05-08 10:48:30.923 6828 6828 I wm_on_destroy_called: [185499341,com.android.settings.Settings,performDestroy] 05-08 10:48:30.937 21802 10690 I wm_task_removed: [49,removeChild: last r=ActivityRecord{b0e7ecd u0 com.android.settings/.Settings t-1 f}} in t=Task{ccf6a93 #49 visible=true type=standard mode=fullscreen translucent=false A=1000:com.android.settings.root U=0 StackId=49 sz=0}] 05-08 10:48:30.937 21802 10690 I wm_task_removed: [49,removeTask] 05-08 10:48:30.938 21802 10690 I wm_task_removed: [49,removeTask] 05-08 10:48:30.938 21802 10690 I wm_stack_removed: 49 05-08 10:49:23.205 21802 21948 I battery_level: [90,4346,256] 05-08 10:49:30.187 21802 21850 I am_uid_idle: 10136 05-08 10:49:30.189 21802 21850 I am_uid_idle: 10107 05-08 10:51:45.883 22174 22174 I service_manager_stats: [100,223,3074203] 05-08 10:51:49.401 21802 23866 I am_kill : [0,9667,android.process.acore,995,empty for 114809s] 05-08 10:51:49.444 21802 25008 I am_proc_died: [0,9667,android.process.acore,995,19] 05-08 10:51:49.452 21802 25008 I am_uid_stopped: 10072 05-08 10:51:49.455 21802 21948 I battery_level: [91,4345,259] 2.3 调整Android log buffer 大小

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

        原因就是Log Buffer太小导致部分Log被冲掉。有时候是客户打印了太多的Log导致。目前默认大小是256K.

   查询Android Log buffer的方法:

备注:  目前默认大小是256K,一般建议设置不超过16M。

方案1. 

    命令: logcat -G Size

    Example:  logcat -G 4M

 

方案2.

    "开发者选项"打开 -> "Developer options" -> "Logger buffer sizes" ->  按需调整

三,实现原理 3.1 日志架构

图片来自于CSDN-私房菜:

3.2 调用流程 3.2.1 写流程

        在应用层可以通过android.util.Log,android.util.SLog,android.util.EventLog接口,把日志写入到main,system,event的不同缓冲区中去。

应用层写日志方法如下:

        在Native C/C++中,进程通过加载liblog.so,调用ALOGD()、ALOGI()来进行日志的写入,最终也是通过logd写入到logdw的socket中。

    Native 层写日志方法如下:

3.2.2 读流程

    Android中主要通过logcat进程来读取日志,logcat属于native-C的进程,通过加载liblog,从而调用logd的read接口读取 logdr socket的日志内容。

四,源码分析

        Android系统日志主要有三个部分需要关注:

            logd守护进程:日志系统的大管家,管理三个日志的socket:logd、logdr、logdw。

            logcat进程:日志读取工具。

            liblog:提供日志读写、过滤等接口,供logcat、JAVA、Native等程序使用

4.1 logd守护进程启动

        见文件/system/core/logd/logd.rc

service logd /system/bin/logd socket logd stream 0666 logd logd socket logdr seqpacket 0666 logd logd socket logdw dgram+passcred 0222 logd logd file /proc/kmsg r file /dev/kmsg w user logd group logd system package_info readproc capabilities SYSLOG AUDIT_CONTROL priority 10 writepid /dev/cpuset/system-background/tasks service logd-reinit /system/bin/logd --reinit oneshot disabled user logd group logd writepid /dev/cpuset/system-background/tasks # Limit SELinux denial generation to 5/second service logd-auditctl /system/bin/auditctl -r 5 oneshot disabled user logd group logd capabilities AUDIT_CONTROL on fs write /dev/event-log-tags "# content owned by logd " chown logd logd /dev/event-log-tags chmod 0644 /dev/event-log-tags on property:sys.boot_completed=1 start logd-auditctl

        从上面的service可以看出,启动了一个守护进程为logd,存放在手机的/system/bin中,同时创建并启动三个socket:

    logd 接收logcat 传递的指令然后处理 ,比如logcat -g, logcat -wrap等

    logdr logcat从此buffer中读取buffer

    logdw 日志写入的buffer

logd初始化调用栈如下:

logd的初始化流程:

    打开/dev/kmsg 来读取内核日志,通过LogKlog来进行存储

    如果属性"ro.logd.kernel" 配置了,打开/proc/kmsg来读取内核日志

    设置运行时优先级、权限

    启动 Reinit线程,当logd-reinit传入参数reinit时,进行调用,reinit开机只启动一次

    启动各个 log 监听器:LogBuffer、LogReader、LogListener、CommandListener、LogAudit和LogKlog

4.2 启动 logd-reinit

        启动logd-reinit的服务,主要工作是重新初始化logd的LogBuffer,在上面的启动脚本中,配置为oneshot,即开机只执行一次。

    通过上面logd的初始化,可以看到,logd启动后,创建了一个线程reinit_thread_start(),当logd-reinit 传入参数 reinit后,进行功能执行。

    logd-reinit两个步骤:

            如果reinit启动后,并且/deg/kmsg打开成功,把 logd.daemon: renit写入kmsg

            重新初始化各个log buffer的大小,以及其他参数的初始化,但不会重新生成LogBuffer对象

4.3 启动 logd-auditctl

logd-auditctl 的主体是 /system/bin/auditctl,在logd的android.bp中,通过编译 auditctl.cpp得来,并加载了liblogd的 库。

    logd-auditctl是Android 10.0中引入的新功能,目的是让selinux denia的日志打印限制为5秒一次。

logd-auditctl 初始化调用栈如下:

logd-auditctl的主要作用是 让selinux denia的日志打印限制为5秒一次

说明:在logd.rc中配置了logd-auditctl,传入参数为-r5,即限制selinux日志写入频率更新为5秒

4.4 logcat启动

        logcat编译时,会编译两个进程/system/bin/logcat 和/system/bin/logcatd。

        和logd一样,logcat进程启动,是init进程解析了logcatd.rc来进行加载。

————————————————

参考:

1,博主「IngresGe」,原文链接:https://blog.csdn.net/yiranfeng/article/details/104244900



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3