现在的位置: 首页 > 综合 > 正文

Logger日志系统实现流程研究

2018年06月10日 ⁄ 综合 ⁄ 共 3542字 ⁄ 字号 评论关闭

综述:日志系统的实现流程

1、应用层应用程序:调用应用程序框架层的java接口,实际是java类的静态函数,android.util.Log(如Log.i());----------应用程序

2、应用框架层java接口:Log的静态方法如(v()、i()、e()),调用本层对应的JNI方法:如:println_native   ------------java类Log jar包:system/framework/framework.jar

3、应用框架层JNI方法:调用运行库层的C接口:如__android_log_buf_write  -C库:libandroid_runtime.so

4、运行库层C接口:通过设备文件类访问内核空间的Logger驱动程序:如write\read   C库:liblog.so

5、驱动程序层:实现日志的操作    -C库:打包进内核

一、应用层android程序写日志

1、导入应用框架层接口类:import android.util.Log

2、调用类的静态函数Log.i(Info_Tag,"This a info log");
二、应用框架层android.util.Log

1、源文件、输出文件及编译方法

源文件:frameworks/base/core/java/android/util/Log.java

输出jar包:system/framework/framework.jar

编译方法:mmm framework/base

2、Log.java日志接口类文件概要说明

public final class Log {
//final class: 当一个类声明为final,决定该类不能被继承,应用框架层接口类一般这样定义
//final data : 用于基本数据类型定义时,其值不可变,相当于定义常量 
//public static 函数:静态函数,属于类,通过类来调用,接口函数一般这样定义 
   
    //定义了2~7一共6个日志优先级别ID,不同的级别调用不同的函数
    public static final int VERBOSE = 2;
    public static final int DEBUG = 3;
    public static final int INFO = 4;
    public static final int WARN = 5;
    public static final int ERROR = 6;
    public static final int ASSERT = 7;
   
    //V优先级的接口函数
    public static int v(String tag, String msg) {
        return println_native(LOG_ID_MAIN, VERBOSE, tag, msg);
    }
    public static int v(String tag, String msg, Throwable tr) {
        return println_native(LOG_ID_MAIN, VERBOSE, tag, msg + '\n' + getStackTraceString(tr));
    }
   
   //d优先级的接口函数
    public static int d(String tag, String msg) {
        return println_native(LOG_ID_MAIN, DEBUG, tag, msg);
    }
    public static int d(String tag, String msg, Throwable tr) {
        return println_native(LOG_ID_MAIN, DEBUG, tag, msg + '\n' + getStackTraceString(tr));
    }
   
   //i优先级的接口函数
    public static int i(String tag, String msg) {
        return println_native(LOG_ID_MAIN, INFO, tag, msg);
    }
    public static int i(String tag, String msg, Throwable tr) {
        return println_native(LOG_ID_MAIN, INFO, tag, msg + '\n' + getStackTraceString(tr));
    }
 
   //w优先级的接口函数
    public static int w(String tag, String msg) {
        return println_native(LOG_ID_MAIN, WARN, tag, msg);
    }
    public static int w(String tag, String msg, Throwable tr) {
        return println_native(LOG_ID_MAIN, WARN, tag, msg + '\n' + getStackTraceString(tr));
    }

    //e优先级的接口函数
    public static int e(String tag, String msg) {
        return println_native(LOG_ID_MAIN, ERROR, tag, msg);
    }
    public static int e(String tag, String msg, Throwable tr) {
        return println_native(LOG_ID_MAIN, ERROR, tag, msg + '\n' + getStackTraceString(tr));
    }

    //日志类型ID,有四个日志类型,对应3个日志缓冲区设备文件,此处接口函数全用main日志缓冲区
    /** @hide */ public static final int LOG_ID_MAIN = 0;//对应设备文件 dev/log/main
    /** @hide */ public static final int LOG_ID_RADIO = 1;//对应设备文件 dev/log/radio
    /** @hide */ public static final int LOG_ID_EVENTS = 2;//对应设备文件 dev/log/enents
    /** @hide */ public static final int LOG_ID_SYSTEM = 3;//对应设备文件 dev/log/main
    
    //声明了println_native本地方法,接口函数通过该方法写入日志
    /** @hide */ public static native int println_native(int bufID,int priority, String tag, String msg);
}

三、应用框架层JNI方法

1、源文件、输出文件及编译方法

源文件:frameworks/base/core/jni/android_util_Log.cpp

输出C库:system/lib/libandroid_runtime.so

编译方法:mmm frameworks/base/core/jni

2、jni方法分析

   实现方法:

//android_util_Log对应android.util.Log类,有jni声明
  static jint android_util_Log_println_native(...) 
  {...
     __android_log_buf_write(...);//调用运行库的方法
    ....
  } 

  定义方法表:

  static JNINativeMethod gMethods[] = {  
    ....
    { "println_native",  "(IILjava/lang/String;Ljava/lang/String;)I", (void*) android_util_Log_println_native },  
};  

注册方法表:

int register_android_util_Log(JNIEnv* env)  
{  
   ....     
    return AndroidRuntime::registerNativeMethods(env, "android/util/Log", gMethods, NELEM(gMethods));  
}  

说明:在gMethods变量中,定义了println_native本地方法对应的函数调用是android_util_Log_println_native。在android_util_Log_println_native函数中,调用运行时库函数__android_log_buf_write来实现Log的写入操作

四、运行库层liblog.so

1、源文件、输出库及编译方法

源文件目录:system/core/liblog/,其中的logd_write.c这个文件实现_android_log_buf_write方法

输出库文件:system/lib/liblog.so

编译方法:mmm  system/core/liblog

2、说明:运行库层函数通过标准的文件操作函数open read write和设备文件描述符fd通过操作系统调用日志驱动程序,从而实现日志的写入

五、Logger驱动程序

抱歉!评论已关闭.