当前位置:   article > 正文

Android的Log系统_android的vsyslog

android的vsyslog

最近看了一点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,

  1. int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
  2. {
  3. struct iovec vec[3];
  4. if (!tag)
  5. tag = "";
  6. /* XXX: This needs to go! */
  7. if (!strcmp(tag, "HTC_RIL") ||
  8. !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
  9. !strcmp(tag, "AT") ||
  10. !strcmp(tag, "GSM") ||
  11. !strcmp(tag, "STK") ||
  12. !strcmp(tag, "CDMA") ||
  13. !strcmp(tag, "PHONE") ||
  14. !strcmp(tag, "SMS"))
  15. bufID = LOG_ID_RADIO;
  16. vec[0].iov_base = (unsigned char *) &prio;
  17. vec[0].iov_len = 1;
  18. vec[1].iov_base = (void *) tag;
  19. vec[1].iov_len = strlen(tag) + 1;
  20. vec[2].iov_base = (void *) msg;
  21. vec[2].iov_len = strlen(msg) + 1;
  22. return write_to_log(bufID, vec, 3);
  23. }

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中有定义

  1. #define LOGGER_LOG_MAIN "log/main"
  2. #define LOGGER_LOG_RADIO "log/radio"
  3. #define LOGGER_LOG_EVENTS "log/events"
  4. #define LOGGER_LOG_SYSTEM "log/system"

初始化设备后,write_to_lo指向__write_to_log_kernel

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

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

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

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

LOG的宏定义如下:

  1. /*
  2. * Simplified macro to send a debug log message using the current LOG_TAG.
  3. */
  4. #ifndef LOGD
  5. #define LOGD(...) ((void)LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__))
  6. #endif
  7. /*
  8. * Basic log message macro.
  9. *
  10. * Example:
  11. * LOG(LOG_WARN, NULL, "Failed with error %d", errno);
  12. *
  13. * The second argument may be NULL or "" to indicate the "global" tag.
  14. */
  15. #ifndef LOG
  16. #define LOG(priority, tag, ...) \
  17. LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
  18. #endif
  19. /*
  20. * Log macro that allows you to specify a number for the priority.
  21. */
  22. #ifndef LOG_PRI
  23. #define LOG_PRI(priority, tag, ...) \
  24. android_printLog(priority, tag, __VA_ARGS__)
  25. #endif
  26. #define android_printLog(prio, tag, fmt...) \
  27. __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)

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

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







声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/728977
推荐阅读
相关标签
  

闽ICP备14008679号