Android LOG机制的实现(5)

三、读LOG操作

select()返回之后,通过循环判定dev->fd是否在readset里被设置(FD_ISSET)[line#3],知道哪个log buffer里已经有数据了。

if (result >= 0) {       for (dev=devices; dev; dev = dev->next) {           if (FD_ISSET(dev->fd, &readset)) {               queued_entry_t* entry = new queued_entry_t();               /* NOTE: driver guarantees we read exactly one full entry */               ret = read(dev->fd, entry->buf, LOGGER_ENTRY_MAX_LEN);      //…  

通过read()读取[line#6]已经有数据的LOG Buffer的文件操作符dev->fd就可得到新到来的log了。

应用程序logcat中已经获取了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。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wyppxz.html