一、前言
logcat作为读取日志的工具,相当于client 的角色;在前两篇文章中,关于logcat如何与其他部分沟通获取日志信息的流程已经介绍的比较清晰,本文不在赘述,转而归纳一下logcat的一些常用指令,并对其中一些做详细分析
二、命令简介
三、日志缓冲区
Android日志系统为日志消息保留了多个环形缓冲区,但并非多有的日志消息都会发送到默认的环形缓冲区。这里可以采用logcat -b命令查看设备的其他缓冲区:
如果需要查看内核空间日志信息,可采用如下几种方式查看:
1、读取/proc/kmsg,命令如下
adb shell cat /proc/kmsg
读取/proc/kmsg属于消费型读取,读取之后再次读取不会显示已经读取过的日志信息
2、读取/dev/kmsg,命令如下
adb shell cat /dev/kmsg
读取/dev/kmsg会显示缓存区里面的所有日志信息。新写入的日志信息会不断累加到日志缓冲器中
3、使用dmesg命令读取
adb shell dmesg
dmesg命令读取一次只显示一部分日志,非阻塞执行
四、格式化输出
使用-v命令来修改log的输出格式,以显示特定的元数据字段:
优先级:
五、logcat -f 命令详解
logcat -f命令可以将日志消息输出到指定的文件中。这里我们需要确定的一件事是logcat作为客户端的角色,会将通过liblog获得的日志信息进行格式解析、格式化处理,而liblog库本身并不存在保存、解析的功能。这里来对-f指令做一下解析:
logcat_main.cpp # main()---> logcat.cpp # android_logcat_run_command()---> __logcat(){......case 'f':if ((tail_time == log_time::EPOCH) && !tail_lines) {tail_time = lastLogTime(optctx.optarg);}// redirect output to a filecontext->outputFileName = optctx.optarg; //注释 ①break;......setupOutputAndSchedulingPolicy() //注释 ②while (...) { //注释 ③int ret = android_logger_list_read(logger_list, &log_msg);if (context->printBinary) {printBinary(context, &log_msg);} else {processBuffer(context, dev, &log_msg);}......}
5.1 注释① :解析 -f 指令
case 'f':if ((tail_time == log_time::EPOCH) && !tail_lines) {tail_time = lastLogTime(optctx.optarg);}// redirect output to a filecontext->outputFileName = optctx.optarg; //注释 ①break;
在_logcat()函数中解析-f指令,设置日志输出文件。例如logcat -f sdcard/log.txt,则context->outputFileName赋值为sdcard/log.txt;
5.2 注释② :设置输出路径
static void setupOutputAndSchedulingPolicy(android_logcat_context_internal* context, bool blocking) {if (!context->outputFileName) return;......// 打开文件获得 fd context->output_fd = openLogFile(context->outputFileName);if (context->output_fd < 0) {logcat_panic(context, HELP_FALSE, "couldn't open output file");return;}......}
5.3 注释③ :写入日志
while (...) { // 调用 liblog 库中的 android_logger_list_read 函数获取日志 int ret = android_logger_list_read(logger_list, &log_msg);if (context->printBinary) { // 根据上面获取的文件 fd ,将日志消息写入文件printBinary(context, &log_msg);} else {processBuffer(context, dev, &log_msg);}
以printBinary()函数为例:
logcat.cpp # printBinary() :
void printBinary(android_logcat_context_internal* context, struct log_msg* buf) {size_t size = buf->len();TEMP_FAILURE_RETRY(write(context->output_fd, buf, size));}
作者:猫咪不吃鱼
链接:/p/26252ee91726
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
如果觉得《Android 日志系统分析(三):logcat》对你有帮助,请点赞、收藏,并留下你的观点哦!