Android log 原理

1-log 分类

Log 分类:1-UI(java)log, 2-C/C++ log, 3-kernel log
Log的等级有Verbose,Debug,Info,Warn,Error

  • Java log
    import android.util.Log,在需要打印Log的地方执行Log.v,Log.d,Log.i,Log.w,Log.e.

  • C/C++ log
    #include
    ALOGV,ALOGD,ALOGI,ALOGW,ALOGE。

  • kernel log

示例部分:
TAG=”MyActivity”;
运行时开启log: 在终端输入:setprop log.tag.MyActivity DEBUG
运行时关闭log: 在终端输入:setprop log.tag.MyActivity INFO

2-log 原理

---> Android 的log,从操作系统分层上来讲,可以分为“Kernel Log”和“User Log”
---> 所谓“Kernel Log”就是内核打印的log。内核里调用printk等接口请求输出kernel log。
  kernel log最后会被打印到/dev/kmsg文件上。可以通过dmesg查看到
---> 所谓“User Log”分为2部分。
      ---->1是Linux的标准输出设备中打印的log(stderr/stdout).
      ---->2是android特有的log流程。如通过android.util.Log类打印的log,eventslog, ALOG() native层log打印.
基本流程图

2.1-java的log流程
"frameworks/base/core/java/android/util/Log.java"
"/frameworks/base/core/jni/android_util_Log.cpp"-----> println_native
"system/core/liblog/logger_write.c---->__android_log_buf_write

    Log.d()--->
            -->public static int d(String tag, String msg)  [Log.java]
               -->android_util_Log_println_native  [android_util_Log.cpp]
                 --->__android_log_buf_write

2.2-C/C++: ALOG / ALOGE / ALOGD
/system/core/liblog/logger_write.c

ALOGD/ALOGE 
     ---> ALOG 
          ---> LOG_PRI
               ---> android_printLog 
                   ---> __android_log_print()
                      ----->__android_log_buf_write() 

"/system/core/liblog" 模块编译生成 "/system/lib(64)/liblog.so".

srw-rw-rw- 1 logd logd 0 1970-01-01 00:00 logd
srw-rw-rw- 1 logd logd 0 1970-01-01 00:00 logdr
s-w--w--w- 1 logd logd 0 1970-01-01 00:00 logdw

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 0222 logd logd
    group root system readproc
    writepid /dev/cpuset/system-background/tasks

logd 模块源码在 /system/core/logd/ 编译的目标是linux可执行文件 "/system/bin/logd"
logcat模块源码在 "/system/core/logcat", 编译目标为 "/system/bin/logcat"
logcatd模块源码在 "/system/core/logcat", 编译目标为 "/system/bin/logcatd"

LOCAL_PATH := $(call my-dir)
logcatLibs := liblog libbase libcutils libpcrecpp
include $(CLEAR_VARS)
LOCAL_MODULE := logcat
LOCAL_SRC_FILES := logcat_main.cpp event.logtags
LOCAL_SHARED_LIBRARIES := liblogcat $(logcatLibs)
LOCAL_CFLAGS := -Werror
include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)
LOCAL_MODULE := logcatd
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := logcatd_main.cpp event.logtags
LOCAL_SHARED_LIBRARIES := liblogcat $(logcatLibs)
LOCAL_CFLAGS := -Werror
include $(BUILD_EXECUTABLE)

2.3-kernel log
通过设置" adb shell setprop logd.kernel true" 可以让logd去抓取 Kernel Log
实现原理其实是把 "/proc/kmsg" 和 "/dev/kmsg" 文件当作socket 文件来使用
/proc/kmsg -->实时监控
/dev/kmsg---> 一次读取

/system/core/logd/main.cpp

int main(int argc, char *argv[]) {
    int fdPmesg = -1;
    bool klogd = property_get_bool("logd.kernel",  ------>setprop logd.kernel true 起作用
                                   BOOL_DEFAULT_TRUE |
                                   BOOL_DEFAULT_FLAG_PERSIST |
                                   BOOL_DEFAULT_FLAG_ENG |
                                   BOOL_DEFAULT_FLAG_SVELTE);
    if (klogd) {
        fdPmesg = open("/proc/kmsg", O_RDONLY | O_NDELAY); "/proc/kmsg"读kernel log
    }
}

3-实现的logcat 系统

采用了locatd 进行实现,实际是service ,在user版本是selinux 权限permissive=1, 开启logd.kernel=true
init.target.rc

service logcatxxx /vendor/bin/init.xxx.logcat.sh
    class main
    user root
    group root

init.xxx.logcat.sh

#!/system/bin/sh
while :
do
logcatd -L -b default,kernel -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n 60
done

备注:
根据实践文档要在user 版本把,logcatd build 到系统
PRODUCT_PACKAGES += logcatd
setprop persist.logd.logpersisted logcatd
chmod 766 /data/misc/logd/

实践:
C/C++ 添加log
使用logcatd打印系统日志

REF:
原文参考连接

你可能感兴趣的:(Android log 原理)