android logcat命令
1. logcat -c 清除已有log信息
2.logcat -b main 显示主缓冲区的log
logcat -b radio 显示无线缓冲区的log
logcat -b events 显示事件缓冲区的log
3.logcat -f [filename] 将log保存到指定的文件中,例如 logcat -b radio -f /data/radio.log
4.logcat -v 设置logcat输出的格式
主要有7种输出格式:
1. brief — Display priority/tag and PID of originating process (the default format).
2. process — Display PID only.
3. tag — Display the priority/tag only.
4. thread — Display process:thread and priority/tag only.
5. raw — Display the raw log message, with no other metadata fields.
6. time — Display the date, invocation time, priority/tag, and PID of the originating process.
7. long — Display all metadata fields and separate messages with a blank lines.
比较常用的是显示时间:logcat -v time &
5.logcat -g 查看缓冲区的大小
logcat -g main
logcat -g radio
logcat -g events
Log机制的一些理解:
1. 系统结构
应用程序调用应用程序框架层的Java接口(android.util.Log)来使用日志系统,这个Java接口通过JNI方法和系统运行库最终调用内核驱动程序Logger把Log写到内核空间中。
2. 关键代码及理解
一. 应用程序框架层日志系统Java接口的实现
代码位置:frameworks/base/core/java/android/util/Log.java文件中,实现日志系统的Java接口:
- public final class Log {
- /**
- * Priority constant for the println method; use Log.v.
- */
- public static final int VERBOSE = 2;
- /**
- * Priority constant for the println method; use Log.d.
- */
- public static final int DEBUG = 3;
- /**
- * Priority constant for the println method; use Log.i.
- */
- public static final int INFO = 4;
- /**
- * Priority constant for the println method; use Log.w.
- */
- public static final int WARN = 5;
- /**
- * Priority constant for the println method; use Log.e.
- */
- public static final int ERROR = 6;
- /**
- * Priority constant for the println method.
- */
- public static final int ASSERT = 7;
- ........................
- public static int v(String tag, String msg) {
- return println_native(LOG_ID_MAIN, VERBOSE, tag, msg);
- }
- public static int d(String tag, String msg) {
- return println_native(LOG_ID_MAIN, DEBUG, tag, msg);
- }
- public static int i(String tag, String msg) {
- return println_native(LOG_ID_MAIN, INFO, tag, msg);
- }
- public static int w(String tag, String msg) {
- return println_native(LOG_ID_MAIN, WARN, tag, msg);
- }
- public static int e(String tag, String msg) {
- return println_native(LOG_ID_MAIN, ERROR, tag, msg);
- }
- public static int println(int priority, String tag, String msg) {
- return println_native(LOG_ID_MAIN, priority, tag, msg);
- }
- ...................
- /** @hide */ public static final int LOG_ID_MAIN = 0;
- /** @hide */ public static final int LOG_ID_RADIO = 1;
- /** @hide */ public static final int LOG_ID_EVENTS = 2;
- /** @hide */ public static final int LOG_ID_SYSTEM = 3;
- /** @hide */ public static native int println_native(int bufID,
- int priority, String tag, String msg);
- }
在logcat中用
logcat ActivityManager:w
命令显示ActivityManager标签中等于或高于WARN级别的Log
其中
- <span style="font-size: 13px; line-height: 19px; "></span><pre name="code" class="java" style="margin-top: 4px; margin-right: 0px; margin-bottom: 4px; margin-left: 0px; background-color: rgb(240, 240, 240); ">LOG_ID_MAIN = 0 LOG_ID_RADIO = 1 LOG_ID_EVENTS = 2 LOG_ID_SYSTEM = 3;
在整个Log接口中,最关键的地方声明了println_native本地方法,所有的Log接口都是通过调用这个本地方法来实现Log的注入。下面我们就继续分析这个本地方法println_native。
二. 应用程序框架层日志系统JNI方法的实现。
在frameworks/base/core/jni/android_util_Log.cpp文件中,实现JNI方法println_native:
- #define LOG_NAMESPACE "log.tag."
- #define LOG_TAG "Log_println"
- #include <assert.h>
- #include <cutils/properties.h>
- #include <utils/Log.h>
- #include <utils/String8.h>
- #include "jni.h"
- #include "utils/misc.h"
- #include "android_runtime/AndroidRuntime.h"
- #define MIN(a,b) ((a<b)?a:b)
- namespace android {
- struct levels_t {
- jint verbose;
- jint debug;
- jint info;
- jint warn;
- jint error;
- jint assert;
- };
- static levels_t levels;
- static int toLevel(const char* value)
- {
- switch (value[0]) {
- case 'V': return levels.verbose;
- case 'D': return levels.debug;
- case 'I': return levels.info;
- case 'W': return levels.warn;
- case 'E': return levels.error;
- case 'A': return levels.assert;
- case 'S': return -1; // SUPPRESS
- }
- return levels.info;
- }
- static jboolean android_util_Log_isLoggable(JNIEnv* env, jobject clazz, jstring tag, jint level)
- {
- #ifndef HAVE_ANDROID_OS
- return false;
- #else /* HAVE_ANDROID_OS */
- int len;
- char key[PROPERTY_KEY_MAX];
- char buf[PROPERTY_VALUE_MAX];
- if (tag == NULL) {
- return false;
- }
- jboolean result = false;
- const char* chars = env->GetStringUTFChars(tag, NULL);
- if ((strlen(chars)+sizeof(LOG_NAMESPACE)) > PROPERTY_KEY_MAX) {
- jclass clazz = env->FindClass("java/lang/IllegalArgumentException");
- char buf2[200];
- snprintf(buf2, sizeof(buf2), "Log tag \"%s\" exceeds limit of %d characters\n",
- chars, PROPERTY_KEY_MAX - sizeof(LOG_NAMESPACE));
- // release the chars!
- env->ReleaseStringUTFChars(tag, chars);
- env->ThrowNew(clazz, buf2);
- return false;
- } else {
- strncpy(key, LOG_NAMESPACE, sizeof(LOG_NAMESPACE)-1);
- strcpy(key + sizeof(LOG_NAMESPACE) - 1, chars);
- }
- env->ReleaseStringUTFChars(tag, chars);
- len = property_get(key, buf, "");
- int logLevel = toLevel(buf);
- return (logLevel >= 0 && level >= logLevel) ? true : false;
- #endif /* HAVE_ANDROID_OS */
- }
- /*
- * In class android.util.Log:
- * public static native int println_native(int buffer, int priority, String tag, String msg)
- */
- static jint android_util_Log_println_native(JNIEnv* env, jobject clazz,
- jint bufID, jint priority, jstring tagObj, jstring msgObj)
- {
- const char* tag = NULL;
- const char* msg = NULL;
- if (msgObj == NULL) {
- jclass npeClazz;
- npeClazz = env->FindClass("java/lang/NullPointerException");
- assert(npeClazz != NULL);
- env->ThrowNew(npeClazz, "println needs a message");
- return -1;
- }
- if (bufID < 0 || bufID >= LOG_ID_MAX) {
- jclass npeClazz;
- npeClazz = env->FindClass("java/lang/NullPointerException");
- assert(npeClazz != NULL);
- env->ThrowNew(npeClazz, "bad bufID");
- return -1;
- }
- if (tagObj != NULL)
- tag = env->GetStringUTFChars(tagObj, NULL);
- msg = env->GetStringUTFChars(msgObj, NULL);
- int res = __android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg);
- if (tag != NULL)
- env->ReleaseStringUTFChars(tagObj, tag);
- env->ReleaseStringUTFChars(msgObj, msg);
- return res;
- }
- /*
- * JNI registration.
- */
- static JNINativeMethod gMethods[] = {
- /* name, signature, funcPtr */
- { "isLoggable", "(Ljava/lang/String;I)Z", (void*) android_util_Log_isLoggable },
- { "println_native", "(IILjava/lang/String;Ljava/lang/String;)I", (void*) android_util_Log_println_native },
- };
- int register_android_util_Log(JNIEnv* env)
- {
- jclass clazz = env->FindClass("android/util/Log");
- if (clazz == NULL) {
- LOGE("Can't find android/util/Log");
- return -1;
- }
- levels.verbose = env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "VERBOSE", "I"));
- levels.debug = env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "DEBUG", "I"));
- levels.info = env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "INFO", "I"));
- levels.warn = env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "WARN", "I"));
- levels.error = env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "ERROR", "I"));
- levels.assert = env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "ASSERT", "I"));
- return AndroidRuntime::registerNativeMethods(env, "android/util/Log", gMethods, NELEM(gMethods));
- }
- }; // namespace android
三. 系统运行库层日志系统的实现。
在system/core/liblog/logd_write.c中,关注写入函数__android_log_buf_write的实现:
- int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
- {
- struct iovec vec[3];
- if (!tag)
- tag = "";
- /* XXX: This needs to go! */
- if (!strcmp(tag, "HTC_RIL") ||
- !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
- !strcmp(tag, "AT") ||
- !strcmp(tag, "GSM") ||
- !strcmp(tag, "STK") ||
- !strcmp(tag, "CDMA") ||
- !strcmp(tag, "PHONE") ||
- !strcmp(tag, "SMS"))
- bufID = LOG_ID_RADIO;
- vec[0].iov_base = (unsigned char *) &prio;
- vec[0].iov_len = 1;
- vec[1].iov_base = (void *) tag;
- vec[1].iov_len = strlen(tag) + 1;
- vec[2].iov_base = (void *) msg;
- vec[2].iov_len = strlen(msg) + 1;
- return write_to_log(bufID, vec, 3);
- }
就先写道这里吧,这主要是我想知道Log是怎么写入radio日志分区中看到的一些东西。大部分来自:
非常感谢