Android中LOG机制详解(下)

2.2、类android.util.Log的JNI实现
类android.util.Log有两个Native方法,它们通过JNI用c/c++中实现。
public static native boolean  isLoggable(String tag,  int  level);
public static native int  println_native( int  bufID,int priority, String tag, String msg);
这两个方法是在 frameworks/base/core/jni/android_util_log.cpp 中实现的。这两个方法分别对应下列两个c/c++函数。
static jboolean  android_util_Log_isLoggable(JNIEnv* env, jobject clazz, jstring tag,  jint  level)
static jint  android_util_Log_println_native(JNIEnv* env, jobject clazz,jint bufID, jint priority, jstring tagObj, jstring msgObj)
isLoggable() 的实现是比较<level>(来自参数)与当前property里设定的“log.tag.<tag>”(<tag>来自参数)的level值,大于或等于都是可记录的。程序实现片断如下
    // LOG_NAMESPACE : “log.tag.”
    // chars: convert from param<tag>
    strncpy(key, LOG_NAMESPACE, sizeof(LOG_NAMESPACE)-1);
    strcpy(key + sizeof(LOG_NAMESPACE) - 1, chars);
    //略
     len = property_get(key, buf, "");
    i nt logLevel = toLevel(buf);
     //略
     return (logLevel >= 0 && level >= logLevel) ? true : false;
println_native() 的实现要负责些。关于此最好对比着 Android LOG机制流程图 来看。
android_util.Log.cpp 中, 函数 android_util_Log_println_native()  调用了 Android_log_buf_write() 函数,而 Android_log_buf_write() 又直接调用了 system/core/liblog/logd_write.c 中的 __android_log_buf_write() 。在 文件 system/core/liblog/logd_write.c 中, __android_log_buf_write() 组织了参数,又调用了 write_to_log 这个函数指针。
write_to_log 这个函数指针是实现的关键。
write_to_log 的定义
static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
write_to_log 初始是指向 __write_to_log_init() 这个函数的。所以第一次执行write_to_log的时候是执行了 __write_to_log_init() 。而如果 write_to_log 不是第一次被执行,它已经在 __write_to_log_init() 里被修改指向了 __write_to_log_kernel()
先看 __write_to_log_init() 的实现:
static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
{
#ifdef HAVE_PTHREADS
    pthread_mutex_lock(&log_init_lock);
#endif
 
     if (write_to_log == __write_to_log_init) {
        log_fds[LOG_ID_MAIN] = log_open("/dev/"LOGGER_LOG_MAIN, O_WRONLY);
        log_fds[LOG_ID_RADIO] = log_open("/dev/"LOGGER_LOG_RADIO, O_WRONLY);
        log_fds[LOG_ID_EVENTS] = log_open("/dev/"LOGGER_LOG_EVENTS, O_WRONLY);
        log_fds[LOG_ID_SYSTEM] = log_open("/dev/"LOGGER_LOG_SYSTEM, O_WRONLY);
 
         write_to_log = __write_to_log_kernel;
 
         if (log_fds[LOG_ID_MAIN] < 0 || log_fds[LOG_ID_RADIO] < 0 ||
                log_fds[LOG_ID_EVENTS] < 0) {
            log_close(log_fds[LOG_ID_MAIN]);
            log_close(log_fds[LOG_ID_RADIO]);
            log_close(log_fds[LOG_ID_EVENTS]);
            log_fds[LOG_ID_MAIN] = -1;
            log_fds[LOG_ID_RADIO] = -1;
            log_fds[LOG_ID_EVENTS] = -1;
            write_to_log = __write_to_log_null;
        }
 
         if (log_fds[LOG_ID_SYSTEM] < 0) {
            log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN];
        }
    }
 
#ifdef HAVE_PTHREADS
    pthread_mutex_unlock(&log_init_lock);
#endif
 
      return  write_to_log(log_id, vec, nr);
}
如果是第一次调用( write_to_log 还指向 __write_to_log_init() ),就打开相应的设备文件,获取描述符,并把 write_to_log 指向 __write_to_log_kernel() 。再在 __write_to_log_kernel() 中具体执行写入文件操作。
再看 __write_to_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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值