Android提供瞭的LOG機制的實現貫穿瞭Java,JNI,本地c/c++實現以及LINUX內核驅動等Android的各個層次,並且簡單明晰,是一個相當不錯的解讀案例。本系列文章針對LOG機制的內部實現機理進行解讀,本文是系列之六,解讀Android的c/c++程序中如何使用LOG機制記錄LOG信息。
c/c++本地庫中實現LOG輸出
通過前面的文章知道Android的Java中通過android.util.Log輸出Log信息,那Android的本地c/c++程序能不能也通過這樣的機制來記錄Log呢?再回頭看Log現有的c/c++的本地實現,答案當然是肯定的,而且是相當簡單。Android直接在頭文件(system/core/include/cutils/log.h)裡定義瞭一些宏就可以很好的實現瞭。
因為,LOG分瞭VERBOSE/DEBUG/INFO/WARN/ERROR/ASSERT等類別,簡單起見,以DEBUG為例的實現來說明。
#ifndef LOGD
#define LOGD(…) LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#endif
#ifndef LOGD_IF
#define LOGD_IF(cond, …) \
( (CONDITION(cond)) \
? LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__) \
: (void)0 )
#endif
#ifndef LOG
#define LOG(priority, tag, …) \
LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
#endif
#ifndef LOG_PRI
#define LOG_PRI(priority, tag, …) \
({ \
if (((priority == ANDROID_LOG_VERBOSE) && (LOG_NDEBUG == 0)) || \
((priority == ANDROID_LOG_DEBUG) && (LOG_NDDEBUG == 0)) || \
((priority == ANDROID_LOG_INFO) && (LOG_NIDEBUG == 0)) || \
(priority == ANDROID_LOG_WARN) || \
(priority == ANDROID_LOG_ERROR) || \
(priority == ANDROID_LOG_FATAL)) \
(void)android_printLog(priority, tag, __VA_ARGS__); \
})
#endif
#define android_printLog(prio, tag, fmt…) \
__android_log_print(prio, tag, fmt)
而這一系列宏,最後還是用到瞭函數__android_log_print()
int __android_log_print(int prio, const char *tag, const char *fmt, …)
{
va_list ap;
char buf[LOG_BUF_SIZE];
va_start(ap, fmt);
vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
va_end(ap);
return __android_log_write(prio, tag, buf);
}
這裡還是調到瞭函數__android_log_write()。這個函數應該很熟悉吧,正是前文敘及的c/c++本地函數實現寫設備文件的地方。
c/c++程序中記錄Log的做法
要在c/c++中記錄Log通常的做法是:
定義自己的TAG_LOG宏;包含頭文件log.h;然後在需要記錄Log的地方直接用LOGV/LOGD/LOGI/LOGW/LOGE即可。
比如,文件lights.c中就在開頭這樣寫,
#define LOG_TAG "lights"
#include <cutils/log.h>
然後在該文件的後續部分,大量的用瞭LOGV/LOGE, etc來記錄LOG。