Logcat使用

介绍

logcat是android中的一个命令行工具,可以用于得到程序的log信息

logcat缓冲区

android log输出量巨大,特别是通信系统的log,因此,android把log输出到不同的缓冲区中,目前定义了四个log缓冲区:
1)Radio:输出通信系统的log
2)System:输出系统组件的log
3)Event:输出event模块的log
4)Main:所有java层的log,遗迹不属于上面3层的log
缓冲区主要给系统组件使用,一般的应用不需要关心,应用的log都输出到main缓冲区中
默认log输出(不指定缓冲区的情况下)是输出System和Main缓冲区的log

logcat命令参数

 
参数 描述
-b <buffer> 加载一个可使用的日志缓冲区供查看,比如event和radio。默认值是main
-c 清除缓冲区中的全部日志并退出(清除完后可以使用-g查看缓冲区)
-d 将缓冲区的log转存到屏幕中然后退出
-f <filename> 将log输出到指定的文件中<文件名>.默认为标准输出(stdout)
-g 打印日志缓冲区的大小并退出
-n <count> 设置日志的最大数目<count>,默认值是4,需要和-r选项一起使用
-r <kbytes> 没<kbytes>时输出日志,默认值是16,需要和-f选项一起使用
-s 设置过滤器
-v <format> 设置输出格式的日志消息。默认是短暂的格式。支持的格式列表
一般长时间输出log的话建议-f,-n,-r三个参数连用,这样当一个文件日志输出满了之后可以马上在另一个中进行输出

优先级语法

优先级使用字符标识,一下优先级从低到高
V –Verbose(最低优先级)
D – Debug
I – Info
W – Warning
E – Error
F – Fatal
S – Silent
为了减少不想要日志的输出,可以建立一个过滤器
过滤语法:tag:priority
//过滤TAG为ActivityManager输出级别大于I的日志与TAG为MyApp输出级别大于D的日志
adb logcat ActivityManager:I  My App:D *:S
adb logcat *:W
设置过滤级别为W以上
如果用的比较多可以设置环境变量:
export ANDROID_LOG_TAGS="ActivityManager:I MyApp:D*:S"

logcat源码分析

logat源码主要分布在:
system/core/logcat/logcat.cpp system/core/include/cutils/logger.h
使用了liblog库,编译出来的结果是可执行程序logcat。
我们从logcat.cpp的main函数开始分析。
主函数代码:
 1 int main(int argc, char **argv)
 2 {
 3     ......
 4  
 5 //1. 参数check和解析
 6     g_logformat = android_log_format_new();
 7  
 8     if (argc == 2 && 0 == strcmp(argv[1], "--test")) {
 9         logprint_run_tests();
10         exit(0);
11     }
12  
13     if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
14         android::show_help(argv[0]);
15         exit(0);
16     }
17  
18    // 参数的继续处理
19     for (;;) {
20         int ret;
21         ret = getopt(argc, argv, "cdt:gsQf:r::n:v:b:B");
22  
23         if (ret < 0) {
24             break;
25         }
26  
27         switch(ret) {
28             case 's': 
29                 // default to all silent
30                 android_log_addFilterRule(g_logformat, "*:s");
31             break;
32  
33             case 'c':
34                 clearLog = 1;
35                 mode = O_WRONLY;
36             break;
37         ......
38     }
39  
40 //2. devices的过滤
41 if (!devices) {
42         devices = new log_device_t(strdup("/dev/"LOGGER_LOG_MAIN), false, 'm');
43         android::g_devCount = 1;
44         int accessmode =
45                   (mode & O_RDONLY) ? R_OK : 0
46                 | (mode & O_WRONLY) ? W_OK : 0;
47         // only add this if it's available
48         if (0 == access("/dev/"LOGGER_LOG_SYSTEM, accessmode)) {
49             devices->next = new log_device_t(strdup("/dev/"LOGGER_LOG_SYSTEM), false, 's');
50             android::g_devCount++;
51         }
52     }
53  
54 //dev = devices;
55     while (dev) {
56         dev->fd = open(dev->device, mode);
57  
58 ......
59  
60 //3.读取一行
61 android::readLogLines(devices);
62 }
  1. 根据输入的参数,进行相应的分析和处理:
例如,输入--help,就调用
    android::show_help(argv[0]);
     //显示help信息。
然后进入for无限循环。在for循环中,进一步进行参数处理。包括getopt中的这些值。
ret = getopt(argc, argv, "cdt:gsQf:r::n:v:b:B");
函数用于过滤参数中是否包含cdt:gsQf:r::n:v:b:B中的值,并且返回这个值。
对于ret的处理就是switch case
  1. 对devices的分析:
devices的类型定义在logger.h中,如下:
    #define LOGGER_LOG_MAIN                "log/main"
    #define LOGGER_LOG_RADIO        "log/radio"
    #define LOGGER_LOG_EVENTS        "log/events"
    #define LOGGER_LOG_SYSTEM        "log/system"
可见,logcat -b后面的参数对应于文件系统中的某一个(几个)文件。
  1. readLines函数的实现:
实现原理,实现一个无限循环,采用select多路复用,从
devices
中获取数据,这里的devices就是前面提到的
system, events , radio, main
多路复用select: 监听devices设备,超时时间设置为5ms。将结果通过read函数读取到内存中,即读取到queued_entry_t相关的内存中。

C 输出log到LogCat

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <jni.h>
 4 #include <android/log.h>
 5  
 6 #define LOG "c_log"
 7 #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE,LOG,__VA_ARGS__)
 8 #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG,__VA_ARGS__)
 9 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG,__VA_ARGS__)
10 #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG,__VA_ARGS__)
11 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG,__VA_ARGS__)
12 #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG,__VA_ARGS__)
13  
14 JNIEXPORT void JNICALL
15 Java_com_myc_jni_Jni_cLog(JNIEnv *env, jobject instance) {
16     LOGV("c输出测试: 等级v");
17     LOGD("c输出测试: 等级d");
18     LOGI("c输出测试: 等级i");
19     LOGW("c输出测试: 等级w");
20     LOGE("c输出测试: 等级e");
21     LOGF("c输出测试: 等级f");
22 }
View Code

 

posted @ 2023-03-14 15:36  kongbursi  阅读(552)  评论(0编辑  收藏  举报