android log.d 参数,android logd 原理及实现

一、logd介绍

logd 是Android L版本提出来的概念,其作用是保存Android运行期间的log(日志)。在Android L之前,log由kernel的ring buffer 保存,在Android L之后,log保存在用户空间。

1)  logd进程启动

系统启动到init函数时会解析init.rc文件,启动logd进程和logd-reinit(重新初始化logd) 进程,init.rc文件中的相关内容如下:

onload_persist_props_action

load_persist_props

start logd

start logd-reinit

在system/core/logd中的logd.rc文件中,启动logdservice和logd-reinit service,具体内容如下:

service logd /system/bin/logd

socket logd stream 0666logd logd

socket logdr seqpacket0666 logd logd

socket logdw dgram 0222logd logd

group root system readproc

writepid/dev/cpuset/system-background/tasks

service logd-reinit /system/bin/logd --reinit

oneshot

disabled

writepid/dev/cpuset/system-background/tasks

注:logd-reinit只会执行一次,logd和logd-reinit都会调用system/core/logd/main.cpp中的main函数,但logd-reinit通过netlink给logd进程发送reinit命令后就会退出。

2)  logd 实现log管理

主要原理是:上层应用(Android层)通过调用Log/Slog/Rlog中的v/d方法打印log,最终log会通过netlink传递给logd,logd会将log保存在内存中(由C++中的list容器管理,后续会介绍),logcat等log获取工具同样通过netlink方式从logd获取log。

二、logd实现流程

本文主要介绍load侧的实现,对于Androidlog如何传递给logd,只做简要介绍。

1.      Android层往logd写log

Android层调用Log/Slog/Rlog中的v/d方法打印log,最终会调用到

system/core/liblog/logger_write.c 中的__android_log_buf_write函数,调用流程如下:

__android_log_buf_write

->write_to_log

->__write_to_log_init

->__write_to_log_initialize

->logdOpen

->__write_to_log_daemon

->logdWrite

文件最终写到 “/dev/socket/logdw”中,此时logd中的LogListener会监测到有log需写入,待log保存后,会通知LogReader将新保存的log传递给logcat等。

2.      Logd log保存机制

在system/core/lodgd/main.cpp文件的main函数中,创建了LogBuffer,LogReader,LogListener和CommandListener四个对象,

LogBuffer用于管理log;

LogReader用于将log传递给logcat;

LogListener用于监听是否有log写入logd;

CommandListener用于监听是否有命令发送给logd。

接下来介绍log的保存流程:

1)  创建LogBuffer对象,在classLogBuffer类中,定义了一个list容器,保存了指向LogBufferElement对象的指针,创建LogBuffer对象时在其构造函数中会调用LogBuffer::init()函数初始化各log域(如main/system/kernel/crash等)的大小。

2)  创建LogListener对象并开始监听

LogListener *swl = newLogListener(logBuf, reader);

// Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value

if(swl->startListener(600)) {

exit(1);

}

3)  在startListener函数中创建线程,线程注册函数为SocketListener::threadStart;

4)  执行runListener函数,如果socket监听到数据,则执行onDataAvailable函数进行处理;

5)  调用logbuf->log(LogBuffer::log),这个函数很重要,新建一个LogBufferElement对象(用于保存log),调用mLogElements.insert将LogBufferElement加入list容器,实现log的保存。

3.

三、Logd-reinit 进程

Logd-reinit 进程在启动时,会给logd进程发送reinit命令,logd在收到命令后,会重新初始化LogBuffer。

在system/core/lodgd/main.cpp文件的main函数中会创建一个线程用于监测是否有reinit请求

if (pthread_create(&thread, &attr,reinit_thread_start, NULL))

在reinit_thread_start函数中,会重新初始化各个log区的大小,以及其他参数的初始化,但不会重新生成LogBuffer对象。相关代码如下:

//Anything that reads persist.

if(logBuf) {

logBuf->init();

logBuf->initPrune(NULL);

}

四、Logd log 获取

可通过logcat工具获取logd log,logcat 相关代码所在路径:system/core/logcat

执行adb logcat 即可查看log

注:通过logcat获取的log,并不完全是按照log分类来打印的,如在KERNEL log中可能存在MAIN log。

logcat实现的大部分函数都在logcat/logcat.cpp文件中,其中__logcat函数是最重要的函数,其负责logcat 输入参数的解析以及log的处理。

logcat 最终读取log通过liblog/logd_reader.c 中的logdRead函数实现。此函数负责打开/dev/logdr,并通过socket获取log。

最近在使用logcat 获取log时,存在log丢失的情况,不知大家是否有遇到过。

调查发现,当同时启动6个线程分别获取main/kernel/system/crash/events等log时,由于启动的线程太多(即多个socket 与server 连接),导致有log丢失。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android SDK下, 如何在程序中输出日志 以及如何查看日志. 闲话少说,直接进入正题 在程序中输出日志, 使用 android.util.Log 类. 该类提供了若干静态方法 Log.v(String tag, String msg); Log.d(String tag, String msg); Log.i(String tag, String msg); Log.w(String tag, String msg); Log.e(String tag, String msg); 分别对应 Verbose, Debug, Info, Warning,Error. tag是一个标识,可以是任意字符串,通常可以使用类名+方法名, 主要是用来在查看日志时提供一个筛选条件. 程序运行后 并不会在 ide的控制台内输出任何信息. 如果要后查看日志 请使用 adb logcat 关于adb的更多信息请查看官方网站. 当执行 adb logcat 后会以tail方式实时显示出所有的日志信息. 这时候我们通常需要对信息进行过滤,来显示我们需要的信息, 这时候我们指定的 tag就派上了用场. adb logcat -s MyAndroid:I 这时将只显示tag为MyAndroid,级别为I或级别高于I(Warning,Error)的日志信息. 示例代码如下: Java代码 1. package com.zijun; 2. 3. import android.app.Activity; 4. import android.content.Context; 5. import android.graphics.Canvas; 6. import android.os.Bundle; 7. import android.util.Log; 8. import android.view.MotionEvent; 9. import android.view.View; 10. 11. public class MyAndroid extends Activity { 12. 13. protected static final String ACTIVITY_TAG="MyAndroid"; 14. 15. @Override 16. protected void onCreate(Bundle icicle) { 17. super.onCreate(icicle); 18. setContentView(new MyView(this)); 19. } 20. public class MyView extends View { 21. public MyView(Context c) { 22. super(c); 23. } 24. @Override 25. protected void onDraw(Canvas canvas) { 26. 27. } 28. @Override 29. public boolean onMotionEvent(MotionEvent event) { 30. Log.i(MyAndroid.ACTIVITY_TAG, "============================="); 31. 32. Log.d(MyAndroid.ACTIVITY_TAG, "Haha , this is a DEBUG of MyAndroid. "); 33. Log.i(MyAndroid.ACTIVITY_TAG, "Haha , this is a INFO of MyAndroid. "); 34. Log.w(MyAndroid.ACTIVITY_TAG, "Haha , this is a WARNING of MyAndroid. "); 35. 36. return true; 37. } 38.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值