android日志系统详解 |
您所在的位置:网站首页 › 建立debug调试日志 › android日志系统详解 |
目录 一,背景介绍 二,基础概念 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" -> 按需调整 图片来自于CSDN-私房菜: 在应用层可以通过android.util.Log,android.util.SLog,android.util.EventLog接口,把日志写入到main,system,event的不同缓冲区中去。 应用层写日志方法如下: 在Native C/C++中,进程通过加载liblog.so,调用ALOGD()、ALOGI()来进行日志的写入,最终也是通过logd写入到logdw的socket中。 Native 层写日志方法如下: 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-auditctllogd-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 |