Android日志系统(logging system)

背景

不管是做Android应用还是做Android中间层和底层,在做一些调试工作的时候,使用adb logcat非常关键。特意学习了一下安卓的log系统。

adb logcat -v time -b all

原文(有删改)出处不详。

参考文档:

概览

Android提供了一个灵活的logging系统,允许应用程序和系统组件等整个系统记录logging信息,它是独立于Linux Kernel的一个logging系统,kernel是通过”pr_info”、”printk”等存储,通过“dmesg”或“cat /proc/kmsg”获取。

不过,Android logging 系统也是将信息存在内核缓存区。

 

Logging system由如下几部分组成:

  • 实现loging信息存储的kernel驱动和缓存区
  • C,C++和Java 类添加与读取log
  • 一个单独浏览log信息的程序(logcat)
  • 能够查看和过滤来自主机的log信息(通过Android Studio 或者 DDMS)

其在kernel中为系统的不同部分提供了四个不同log缓存区,可以通过/dev/log查看这些不同的设备节点,如下:

  • /dev/log/mian : 主应用程序log,除了下三个外,其他用户空间log将写入此节点,包括System.out.print及System.erro.print等
  • /dev/log/events : 系统事件信息,二进制log信息将写入此节点,需要程序解析
  • /dev/log/radio : 射频通话相关信息,tag 为"HTC_RIL" "RILJ" "RILC" "RILD" "RIL" "AT" "GSM" "STK"的log信息将写入此节点
  • /dev/log/system : 低等级系统信息和debugging,为了防止mian缓存区溢出,而从中分离出来

log中的每条信息主要由四部分组成,如下:

  • Tag
  • 时间戳
  • log信息level(或者event的优先级)
  • log信息

Android logger

logging的kernel driver部分被称作”logger”,其为系统日志提供支持,代码路径: kernel/drivers/staging/android/logger.c,此文件对4种logging缓存区加以支持。

驱动

Log的读写是通过正常Linux文件读写方式完成的,write path被很好的优化过,所以能很快的open()、write()及close(),这样就避免了logging在系统中有太多的开销,影响速度。  

Reading

在用户空间,一个正常的read操作通常读取从log读取一个条目,每read一次返回一个log条目或者阻塞等待下一个log条目。设备可以打开非阻塞模式。每一个read请求应该至少请求LOGGER_ENTRY_MAX_LEN (4096)长度的数据。  

Writing

当系统写数据到log时,driver将为每一个log条目保存pid(进程ID),tgid(线程组ID),timestamp(时间戳),这些信息将出现在用户空间的level,tag和message中。  

Ioctl

Ioctl函数支持如下cmd:

  • LOGGER_GET_LOG_BUF_SIZE : log条目缓存区的大小

  • LOGGER_GET_LOG_LEN : log数据的长度

  • LOGGER_GET_NEXT_ENTRY_LEN: 下一log条目的大小

  • LOGGER_FLUSH_LOG : 清除log数据

  • LOGGER_GET_VERSION : 获得logger版本

  • LOGGER_GET_VERSION : 设置logger版本

设备节点

当一个用户空间执行的程序用合适的主设备号和次设备号打开设备节点后,设备节点就处于活动状态,这些设备节点如下:

root@msm8916_32:/ # ls -al dev/log
ls -al dev/log
crw-rw-rw- root log 10, 61 1970-01-09 02:14 events
crw-rw-rw- root log 10, 62 1970-01-09 02:14 main
crw-rw-rw- root log 10, 60 1970-01-09 02:14 radio
crw-rw-rw- root log 10, 59 1970-01-09 02:14 system

所有的log信息在Java类中定义并做相应处理,最终一个格式化的消息通过C/C++库传递到内核驱动程序,然后再将消息存储在适当的缓冲区中。

App log

App通过导入android.util.Log包来引入Log类,然后通过log方法写不同优先级的相关信息到log。

Java类定义传递到log方法的tag为字符串常量,log方法通过这些字符串来获知信息的重要性,这样,当我们用log查看工具(如logcat)时,就可以过滤tag或者优先级来获取我们想要的信息。如下:

root@msm8916_32:/ # logcat
logcat
--------- beginning of system
I/Vold ( 265): Vold 2.1 (the revenge) firing up
D/Vold ( 265): Volume sdcard1 state changing -1 (Initializing) -> 0 (No-Media)
D/Vold ( 265): Volume uicc0 state changing -1 (Initializing) -> 0 (No-Media) D/Vold ( 265): Volume usbotg state changing -1 (Initializing) -> 0 (No-Media) D/Vold ( 265): Volume uicc1 state changing -1 (Initializing) -> 0 (No-Media)
I/Cryptfs ( 265): Check if PFE is activated on Boot
E/Cryptfs ( 265): Bad magic for real block device /dev/block/bootdevice/by-name/userdata
E/Cryptfs ( 265): Error getting crypt footer and key
I/irsc_util( 316): irsc tool created:0xb70ff688
I/irsc_util( 316): Starting irsc tool
I/irsc_util( 316): Trying to open sec config file

Event log

Event logs是在android.util.EventLog.class中创建二进制log信息。

Log条目由二进制tag代码和二进制参数构成。

Event logs 文件存储在system/etc/event-log-tags中,通过cat system/etc/event-log-tags能查看其信息。

如下:

root@msm8916_32:/ # cat system/etc/event-log-tags
cat system/etc/event-log-tags
42 answer (to life the universe etc|3)
314 pi
1003 auditd (avc|3)
2718 e
2719 configuration_changed (config mask|1|5)
2720 sync (id|3),(event|1|5),(source|1|5),(account|1|5)
2721 cpu (total|1|6),(user|1|6),(system|1|6),(iowait|1|6),(irq|1|6),(softirq|1|6)
2722 battery_level (level|1|6),(voltage|1|1),(temperature|1|1)
2723 battery_status (status|1|5),(health|1|5),(present|1|5),(plugged|1|5),(technology|3)
2724 power_sleep_requested (wakeLocksCleared|1|1)
2725 power_screen_broadcast_send (wakelockCount|1|1)
2726 power_screen_broadcast_done (on|1|5),(broadcastDuration|2|3),(wakelockCount|1|1)
2727 power_screen_broadcast_stop (which|1|5),(wakelockCount|1|1)
2728 power_screen_state (offOrOn|1|5),(becauseOfUser|1|5),(totalTouchDownTime|2|3),(touchCycles|1|1)
2729 power_partial_wake_state (releasedorAcquired|1|5),(tag|3)
2730 battery_discharge (duration|2|3),(minLevel|1|6),(maxLevel|1|6)
2740 location_controller

System log

framework层的许多类通过使用system log 来与app的log信息区分开来。System log在android.util.Slog.clash中实现。

log命令行工具

log命令行工具能用来给任意程序穿件log条目,此工具是内建与toolbox的多功能程序。在adb shell中输入log则会提示其用法,如下:

C:\Users\Administrator>adb shell
root@msm8916_32:/ # log
log
USAGE: log [-p priorityChar] [-t tag] message
priorityChar should be one of:
v,d,i,w,e

toolbox: 具有管理内存、备份和数据清除功能的一个系统文件,用来对手机性能进行设置,需要root权限,能被软件调用。 

logwrapper

logwrapper工具是用来捕捉stdout信息的,当需要从本地应用捕捉stdout信息到log时,它将十分有用。

源码路径:system/core/logwrapper/logwrapper.c;用法如下:

root@msm8916_32:/ # logwrapper
logwrapper
Usage: logwrapper [-a] [-d] [-k] 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. -a: Causes logwrapper to do abbreviated logging.
This logs up to the first 4K and last 4K of the command
being run, and logs the output when the command exits
-d: Causes logwrapper to SIGSEGV when BINARY terminates
fault address is set to the status of wait()
-k: Causes logwrapper to log to the kernel log instead of
the Android system log

Logcat命令

我们可以通过logcat命令查看log,这个命令文件在文件系统的system/bin目录下,所以我们可以到文件系统中执行logcat,或者直接adb logcat,都能查看log。

  • 每一个有tag和优先级的log信息
  • 可以通过tag和log等级过滤log信息
  • 可以通过系统属性指定程序将stdout和stderr内容写入日志

在启动阶段默认打开Logcat

Android logging和kernel logging是完全不同的两种日志系统,另补充一点,kernel日志支持直接在用户空间向/dev/kmsg写入log条目。groups.google.com中介绍了如何在启动阶段launch Logcat,如下:

it can be launched via init.rc as below.. 

service logcat /system/bin/logcat -f /dev/kmsg
oneshot

不推荐这样做,这样会增加打印开销,使系统卡顿 

Android日志系统(logging system)的更多相关文章

  1. Android日志系统驱动程序Logger源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6595744 我们知道,在Android系统中, ...

  2. Android日志系统Logcat源代码简要分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6606957 在前面两篇文章Android日志系 ...

  3. Android应用程序框架层和系统运行库层日志系统源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6598703 在开发Android应用程序时,少 ...

  4. Android日志监听工具logcat命令详解(转)

    Android日志系统提供了记录和查看系统调试信息的功能.日志都是从各种软件和一些系统的缓冲区中记录下来的,缓冲区可以通过logcat命令来查看和使用. 在使用logcat之前,请确保手机的USB调试 ...

  5. ACE日志系统

    引用于:http://blog.csdn.net/focusonace/article/details/3108873 http://peirenlei.iteye.com/blog/305036 介 ...

  6. Android源码——Logger日志系统

    Android的Logger日志系统是基于内核中的Logger日志驱动程序实现的. 日志保存在内核空间中 缓冲区保存日志   分类方法:日志的类型  +   日志的输出量   日志类型:   main ...

  7. Android Logger日志系统

    文件夹 文件夹 前言 执行时库层日志库liblog 源代码分析 CC日志写入接口 Java日志写入接口 logcat工具分析 基础数据结构 初始化过程 日志记录的读取过程 前言 该篇文章是我的读书和实 ...

  8. 图解Android - System Service 概论 和 Android GUI 系统

    通过 图解Android - Binder 和 Service 一文中,我们已经分析了Binder 和 Service的工作原理.接下来,我们来简要分析Android 系统里面都有哪些重要的Servi ...

  9. 图解Android - Android GUI 系统 (5) - Android的Event Input System

    Android的用户输入处理 Android的用户输入系统获取用户按键(或模拟按键)输入,分发给特定的模块(Framework或应用程序)进行处理,它涉及到以下一些模块: Input Reader: ...

  10. Python logging日志系统

    写我小小的日志系统 配置logging有以下几种方式: 1)使用Python代码显式的创建loggers, handlers和formatters并分别调用它们的配置函数: 2)创建一个日志配置文件, ...

随机推荐

  1. 01 go-zero入门--单体服务demo

    目录 官方文档: 视频地址: 系统环境: 配置环境: 1. golang安装 2. go module配置 3. goctl安装 4.protoc,protoc-gen-go,protoc-gen-g ...

  2. ExpiringMap学习总结

    一.ExpiringMap简介 ExpiringMap是一个轻量级的Java缓存方式 针对一些小体量的项目,存储的数据量也不是很大(如校验码)的情况下,使用Redis会增加系统的复杂性和维护难度.它的 ...

  3. MAPREDUCE实践篇

    1.编程规范 (1)用户编写的程序分成三个部分:Mapper,Reducer,Driver(提交运行mr程序的客户端) (2)Mapper的输入数据是KV对的形式(KV的类型可自定义) (3)Mapp ...

  4. 微信小程序校园跑腿系统怎么做,如何做,要做多久

    ​ 在这个互联网快速发展.信息爆炸的时代,人人都离不开手机,每个人都忙于各种各样的事情,大学生也一样,有忙于学习,忙于考研,忙着赚学分,忙于参加社团,当然也有忙于打游戏的(还很多),但生活中的一些琐事 ...

  5. 使用Redis实现短信登陆

    使用Redis实现发送验证码:验证码登陆.注册:登陆校验拦截.登陆状态刷新等一系列问题. 验证码发送和验证登陆注册 思路流程 整体的思路以及流程如题: 代码实现 实体类 User实体类 @Data @ ...

  6. 京东面试:SpringBoot同时可以处理多少请求?

    Spring Boot 作为 Java 开发中必备的框架,它为开发者提供了高效且易用的开发工具,所以和它相关的面试题自然也很重要,咱们今天就来看这道经典的面试题:SpringBoot同时可以处理多少个 ...

  7. 解决 C# 连接oracle 读出中文乱码的问题

    一开始,我使用odbc连接oracle,发现中文变成了??,这种已经成了??的乱码是不能通过 Text.Encoding的方式来转码的. 1.我到处查资料,发现有说设置客户端 系统变量 把 远程服务器 ...

  8. Flask学习记录:在w3cschool资料的基础上的个人摘录、实践与总结

    学习与转载自w3cschool,在w3cschool资料的基础上的个人摘录.实践与总结,如有错误望留言. 一.Flask 概述 2021-08-25 14:01 更新 1.1 什么是Web Frame ...

  9. docker资源限制与数据持久化

    1. docker简介和核心概念 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化.容器是完全使 ...

  10. Go的接口与多态

    什么是Go的接口? 接口可以说是一种类型,可以粗略的理解为他的变量是一堆方法. 一个简单的案例: r,_ := http.Get("http://www.baidu.com") i ...