本帖最后由 jcky001 于 2024-2-6 16:13 编辑
在我们嵌入式开发中,打印日志是最常用的一种调试手段。合理地打印日志,可以帮助我们快速地分析问题。
本篇文章我们来汇总一些嵌入式打log的一些规则。
1、什么操作下加日志?
(1)错误处理
对于不能恢复的严重错误,日志内容应详细到足以帮助定位问题,但同时不应该包含敏感信息。比如申请内存失败时使用错误(Error)级别加上日志信息。
(2)一些关键性的操作
一些很关键地处理,无论是正常情况或者异常情况都要打印日志。比如wifi打开时要有对应的日志信息。
(3)系统的打开、关闭
记录系统启动和关闭过程中的关键步骤有助于分析系统初始化是否正确,或者系统是否正常关闭。
(4)性能监控
日志可以记录系统运行的关键性能指标,比如CPU和内存使用率、IO操作等,以便进行系统性能分析和优化。
(5)关键数据
一些关键数据需要打印,很多功能上的问题大多直接与数据进行挂钩。
(6)通信日志
对于需要与外部设备或网络通信的嵌入式系统,记录通信日志可以帮助分析和调试通信协议或数据交换的问题。
(7)记录用户行为
在需要分析用户如何与嵌入式设备交互的情况下,记录用户行为的日志会非常有帮助。
(8)if、switch
分支判断中,各执行分支需要加上对应的日志信息,可以帮助我们准确地知道程序执行的走向。
(9)程序崩溃时的信息
比如,Linxu下应用进程崩溃时的调用堆栈信息。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <execinfo.h>
void func0(void)
{
printf("This is func0\n");
int *p = NULL;
*p = 1234;
}
void func1(void)
{
printf("This is func1\n");
func0();
}
void func2(void)
{
printf("This is func2\n");
func1();
}
void dump(int signo)
{
void *array[100];
size_t size;
char **strings;
size = backtrace(array, 100);
strings = backtrace_symbols(array, size);
printf("Obtained %zd stacks.\n", size);
for(int i = 0; i < size; i++)
{
printf("%s\n", strings);
}
free(strings);
exit(0);
}
int main(int argc, char **argv)
{
printf("==================segmentation fault test5==================\n");
signal(SIGSEGV, &dump);
func2();
return 0;
}
2、功能模块标签
项目中肯定会划分有多个模块,可以给各个模块标记一个模块标签字符串,包含在日志条目里。这样我们就可以在日志文件里通过模块标签来筛选某个模块的日志,提高我们定位问题的效率。
比如:
// app_wifi.c
#define LOG_TAG "[wifi_module]"
#define LOG_D(fmt, arg...) LOG_D_TAG(LOG_TAG, fmt, ##arg)
LOG_D("hello wifi module");
输出:
[wifi_module]hello wifi module
3、模块日志开关
设置模块日志开关,可以方便我们调试、分析问题时,缩小分析范围。当我们的函数设计有多个功能函数模块的时候,当某个模块出现问题时,这个时候我们只是关心此模块,那么可以先把其他模块的日志功能关闭掉,只是打开关心模块的日志。
比如:
// module1.c
#include "module1.h"
#if MODULE1_LOG_SWITCH
#define LOG_MODULE1(fmt, args...) DBG_PRINTF(fmt, ##args)
#else
#define LOG_MODULE1(fmt, args...)
#endif
// module2.c
#include "module2.h"
#if MODULE2_LOG_SWITCH
#define LOG_MODULE2(fmt, args...) DBG_PRINTF(fmt, ##args)
#else
#define LOG_MODULE2(fmt, args...)
#endif
// config.h
#define MODULE1_LOG_SWITCH 0
#define MODULE2_LOG_SWITCH 1 |