前语
一般来说,初学编程者所写的第一个程序,便是运用printf打印“Hello world”。其实printf的成效远不只这些,在程序调试方面,printf也有十分大的用途。
“蜗蜗”在触摸Linux driver开发之前,学习过桌面程序开发(如Turbo C、Visual C等),也从事了一段时间的嵌入式软件开发。这些开发有一个共同点,对调试东西十分依靠,如桌面程序的Debugger(调试器)、嵌入式开发的仿真器(JTAG等)。还依稀记得,刚作业时,为了插空运用仿真器,不得不趁周末他人不作业时加班运用。直到后来从事Linux driver开发、才智到了printk的魅力之后,多年来,就再也没有运用过仿真器或许调试器了。
下面我就总结一下运用日志打印辅佐debug的心得。
日志打印的注意事项
在编写程序后,咱们能够顺手在需求的当地参加打印信息,一起需求考虑如下事项:
1. 日志输出是有价值的,特别是在嵌入式体系,或许对履行时序要求较高的运用场景。因而
a) 只需在需求的当地参加,不能乱用
b) 必定要有一个大局的开关,在不需求或许产品发布的时分,封闭输出,或许下降日志输出的频率
2. 日志输出需求有优先级操控,例如:产生错误时的日志优先级最高,一般都要输出;一些重要的提示,优先级中等,或许会在debug版的软件中翻开;一些不重要的提示,或许只会在需求的时分(例如盯梢bug)翻开
3. 不要直接运用printf(或许printk)。日志输出的方针是多样的,例如经过printf输出到屏幕、经过串口输出到串口调试帮手、经过文件操作写入到文件等等。要经过重界说的方法,将一切的日志输出指令界说到适宜的输出途径,当需求修正输出途径的时分,只需修正重界说的部分即可。不然需求在整个代码中修正,就麻烦了
4. 最好为每个软件模块供给独自的日志输出开关,以添加调试的灵活性
5. 许多时分,日志输出句子,能够部分替代代码注释的功用
日志打印的完成
结合上面的注意事项,咱们能够依照如下过程完成一个小型的日志输出体系。
Step1. 新建debug.h(假如只是在PC上运用printf,则只需求一个头文件即可。假如有需求文件或许串口操作,能够在这个基础上添加debug.c,这儿暂时不再描绘)
Step2. 界说一个宏开关,用于操控日志输出的开关
/*
* debug control, you can switch on (delete 'x' suffix)
* to enable log output and assert mechanism
*/
#define CONFIG_ENABLE_DEBUG
Step3. 界说ERR、INFO、DEBUG三个日志等级
/*
* debug level,
* if is DEBUG_LEVEL_DISABLE, no log is allowed output,
* if is DEBUG_LEVEL_ERR, only ERR is allowed output,
* if is DEBUG_LEVEL_INFO, ERR and INFO are allowed output,
* if is DEBUG_LEVEL_DEBUG, all log are allowed output,
*/
enum debug_level {
DEBUG_LEVEL_DISABLE = 0,
DEBUG_LEVEL_ERR,
DEBUG_LEVEL_INFO,
DEBUG_LEVEL_DEBUG
};
Step4. 假如运用体系的printf,需求包括stdio.h,并将printf重界说为PRINT(无论是Windows仍是Linux,皆是如此,假如是嵌入式渠道,能够自界说PRINT接口)
/* it can be change to others, such as file operations */
#include
#define PRINT printf
Step5. 界说一个宏,用于界说日志输出等级
/*
* the macro to set debug level, you should call it
* once in the files you need use debug system
*/
#define DEBUG_SET_LEVEL(x) staTIc int debug = x
需求在每一个需求日志输出的C文件中调用,如下:
/*
* define the debug level of this file,
* please see 'debug.h' for detail info
*/
DEBUG_SET_LEVEL(DEBUG_LEVEL_ERR);
Step6. 界说ASSERT、ERR、INFO、DEBUG等宏
#define ASSERT() \
do { \
PRINT(“ASSERT: %s %s %d”, \
__FILE__, __FUNCTION__, __LINE__); \
while (1); \
} while (0)
#define ERR(…) \
do { \
if (debug >= DEBUG_LEVEL_ERR) { \
PRINT(__VA_ARGS__); \
} \
} while (0)
…
Step7. 在需求日志输出的C文件中,包括debug.h,并界说所需的日志等级。就能够在需求的时分输出日志信息了
debug_test.c
—————————————————–
#include “debug.h”
/*
* define the debug level of this file,
* please see 'debug.h' for detail info
*/
DEBUG_SET_LEVEL(DEBUG_LEVEL_ERR);
int main(void) {
ERR(“This is a error message\n”);
INFO(“This is a info message\n”);
DEBUG(“This is a debug message\n”);
ASSERT();
return 0;
}
Step8. 能够根据需求,修正容许输出的日志等级