最近看了一点android关于log的代码,小结一下。

对开发者来说,Log读主要调用工具logcat,后面附带一些参数,

写的话JAVA或者C/C++都有相应的接口。

代码位置:

frameworks/base/core/java/android/util/Log.java

system/core/liblog

system/core/logcat

frameworks/base/core/jni/android_util_Log.cpp


写过程:

JAVA层的frameworks/base/core/java/android/util/Log.java通过JNI掉本地方法__android_log_buf_write,

int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg){    struct iovec vec[3];    if (!tag)        tag = "";    /* XXX: This needs to go! */    if (!strcmp(tag, "HTC_RIL") ||        !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */        !strcmp(tag, "AT") ||        !strcmp(tag, "GSM") ||        !strcmp(tag, "STK") ||        !strcmp(tag, "CDMA") ||        !strcmp(tag, "PHONE") ||        !strcmp(tag, "SMS"))            bufID = LOG_ID_RADIO;    vec[0].iov_base   = (unsigned char *) &prio;    vec[0].iov_len    = 1;    vec[1].iov_base   = (void *) tag;    vec[1].iov_len    = strlen(tag) + 1;    vec[2].iov_base   = (void *) msg;    vec[2].iov_len    = strlen(msg) + 1;    return write_to_log(bufID, vec, 3);}

write_to_log是函数指针,初始化为__write_to_log_init

static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;


__write_to_log_init打开log设备文件,这些设备文件在logger.h中有定义

#define LOGGER_LOG_MAIN     "log/main"#define LOGGER_LOG_RADIO    "log/radio"#define LOGGER_LOG_EVENTS   "log/events"#define LOGGER_LOG_SYSTEM   "log/system"

初始化设备后,write_to_lo指向__write_to_log_kernel

static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr){    ssize_t ret;    int log_fd;    if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) {        log_fd = log_fds[(int)log_id];    } else {        return EBADF;    }    do {        ret = log_writev(log_fd, vec, nr);    } while (ret < 0 && errno == EINTR);    return ret;}
log_id指向对应打开的log设备,然后获取文件描述符,将log信息写入文件,id在Log.java中有定义

    /** @hide */ public static final int LOG_ID_MAIN = 0;    /** @hide */ public static final int LOG_ID_RADIO = 1;    /** @hide */ public static final int LOG_ID_EVENTS = 2;    /** @hide */ public static final int LOG_ID_SYSTEM = 3;

对于C/C++,只需引用<utils/Log.h>头文件,并且定义LOG_TAG宏,在log.h中有如下宏定义

#ifndef LOG_TAG                                                               #define LOG_TAG NULL                                                          #endif 
因此你注意避免LOG_TAG的定义有冲突

LOG的宏定义如下:

/* * Simplified macro to send a debug log message using the current LOG_TAG. */#ifndef LOGD#define LOGD(...) ((void)LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__))#endif/* * Basic log message macro. * * Example: *  LOG(LOG_WARN, NULL, "Failed with error %d", errno); * * The second argument may be NULL or "" to indicate the "global" tag. */#ifndef LOG#define LOG(priority, tag, ...) \    LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)#endif/* * Log macro that allows you to specify a number for the priority. */#ifndef LOG_PRI#define LOG_PRI(priority, tag, ...) \    android_printLog(priority, tag, __VA_ARGS__)#endif#define android_printLog(prio, tag, fmt...) \    __android_log_print(prio, tag, fmt)

__android_log_print最后会调用到__android_log_write函数,完成写入过程。


读过程:

可想而知,读的过程也是打开对应的设备文件,读取里面的log信息。

读log一般都是在minicom或adb shell中执行logcat命令

logcat.cpp里的main函数是该命令的入口

其中-b参数选择对应buffer,也就是对应的设备文件,-c清空buffer,-g获取buffer大小,-f设置log输出设备。

获取命令行里的设备列表之后,打开设备,调用readLogLines从设备中读取log信息到queued_entry_t队列中

static void readLogLines(log_device_t* devices)

            for (dev=devices; dev; dev = dev->next) {                FD_SET(dev->fd, &readset);            }            result = select(max + 1, &readset, NULL, NULL, sleep ? NULL : &timeout);

android_log_printLogLine负责将queued_entry_t队列中的log打印到g_outFD描述符的设备里,如果-f没有设置,则打印到标准输出。







更多相关文章

  1. NPM 和webpack 的基础使用
  2. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
  3. android的adb详解(多设备时adb调用)
  4. Android(安卓)Drawable Resource学习(一)、Drawable Resource简介
  5. 接触Android
  6. Android内核的简单分析
  7. android下 抓包
  8. assets android 获取流 转为string
  9. Android(安卓)音频系统(二)之 AudioFlinger

随机推荐

  1. Android-解决AutoCompleteText下拉提示的
  2. Android(安卓)Studio---创建java项目
  3. Google Map无法显示:Error contacting Goo
  4. Android模拟器代理上网设置[图文详解]
  5. 高焕堂的Android平台应用软体开发ppt
  6. android 区分按键长按及短按
  7. android判断当前sdk版本以及是否是平板
  8. Android中Message的基本使用
  9. AndroidStudio中导入module详细介绍
  10. Android移植