Interpreting the implementation of the android Log Mechanism: (3) Writing Device Files in JNI and C/C ++ Domains
Tian haili @ csdn
Android provides a user-level lightweight Log Mechanism. Its implementation runs through Java, JNI, local C/C ++ implementation, Linux kernel driver, and Other Android layers, it is simple and clear enough to explain the case. This series of articles explains the internal implementation mechanism of the log mechanism. This article is part 3 of this series, interpreting android. util. the JNI Implementation of log, and how to operate the device file to write log information in the local implementation of C/C ++.
JNI Implementation of log-like
As mentioned above, Android. util. log has two native methods, which must be implemented in C/C ++ through JNI.
public static native boolean isLoggable(String tag, int level);public static native int println_native(int bufID, int priority, String tag, String msg);
These two methods are implemented in frameworks/base/CORE/JNI/android_util_log.cpp. How to Implement JNI is not described here. However, these two methods are transferred to the call of the following two C/C ++ functions.
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)
Implementation of isloggable ()
The implementation of isloggable is a comparison between <level> (from the parameter) and the "log. tag. the value of <tag> "(<tag> from parameter) is record if it is greater than or equal. The program implementation snippets are as follows:
// 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, ""); int logLevel = toLevel(buf); return (logLevel >= 0 && level >= logLevel) ? true : false;
Println_native () Implementation
FunctionAndroid_util_log_println_native ()[File android_util.log.cpp] called_ Android_log_buf_write ()[File System/CORE/liblog/logd_write.c]._ Android_log_buf_write ()The parameters are organized and called again.Write_to_logThis function pointer.
Write_to_logThis function pointer is the key to implementation.
See the definition of 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_logInitially, it points to the function _ write_to_log_init. Therefore, when write_to_log is executed for the first time, _ write_to_log_init () is executed (). If write_to_log is not executed for the first time, it has been modified in _ write_to_log_init () to point to _ write_to_log_kernel ().
First look_ Write_to_log_init() Implementation:
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);}
Basically, mutual access protection is implemented. If it is the first call (write_to_log also points to _ write_to_log_init (), the corresponding device file is opened to obtain the descriptor, and point write_to_log to _ write_to_log_kernel (). Then, write the file in _ write_to_log_kernel.
Look at the implementation of _ write_to_kernel (), which is basically a write operation:
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;}
To sum up, the println_native () operation is to open the device file (if it has not been opened) and then write data. But how to write it depends on the implementation of the logger driver of the log device.
[This series of articles]
Interpreting the implementation of the android Log Mechanism: (1) implementation architecture of log
Interpret the implementation architecture of the log mechanism.
Interpreting the implementation of the android Log Mechanism: (2) Java domain output log
Explain how the android Java program outputs log information to the log system.
Interpreting the implementation of the android Log Mechanism: (3) Writing Device Files in JNI and native Domains
Interpret the JNI Implementation of Android. util. log and how to operate the device file to write log information in the local implementation of C/C ++.
Interpreting the implementation of the android Log Mechanism: (4) Log Device-driven Logger
Interpret the implementation of the device driver logger in the Linux kernel. Logger is a misc Driver written by Android for Linux. It uses cyclic queues to implement readers/writers. Logger is the core of the implementation of the entire log mechanism.
Interpreting the implementation of the android Log Mechanism: (5) Obtaining the log program logcat
Explains how the application logcat obtains log information through open ()/select ()/read () of the device file.
Interpreting the implementation of the android Log Mechanism: (6) using log in the C/C ++ domain
This article explains how to use the Log Mechanism in the C/C ++ program of Android to record log information.