1. 做实验引发的思考

在学习LiteOS日志打印组件使用的时候,我记录了一篇博客:atiny_log | LiteOS 物联网操作系统中的日志打印组件使用分享,关于实验的具体内容,请阅读这篇博客(点击阅读原文即可访问)。

在实验时我编写了如下的5行代码:

ATINY_LOG(LOG_DEBUG, "This is a LOG_DEBUG Test!rn");ATINY_LOG(LOG_INFO, "This is a LOG_INFO Test!rn");ATINY_LOG(LOG_WARNING, "This is a LOG_WARNING Test!rn");ATINY_LOG(LOG_ERR,"This is a LOG_ERR Test!rn");ATINY_LOG(LOG_FATAL, "This is a LOG_FATAL Test!rn");

串口的输出如下:

在串口输出的信息中:

① 第一个方括号是该条日志的输出等级:可以用宏定义选择Debug、INFO、WARNING、ERR、FATAL五个等级中的一个;

② 第二个方括号是RTOS在打印信息时的tick值,可以理解为系统当前的时间戳;

③ 最后一个方括号是指定的打印内容;

可让我感到非常疑惑不解的是:

第三个方括号中竟然打印的是该条打印语句所在的函数名称和所在文件中的位置(行数),并且打印出的行号和实际对应,这个在实际应用中用来定位问题非常方便:

经过一番查看源码,我终于探索出程序为什么可以知道并且打印出代码所在位置的~

2. 揭晓谜底

其实,这些RTOS系统之所以准确的打印出了代码所在函数及所在位置,不是用于了多么复杂高深的技术,同样也只是在代码里巧妙的利用了C语言的一个不常用知识点 —— 编译器内置宏定义

C语言编译器中内置了一些宏定义,这些内置宏定义可以巧妙地帮我们输出非常有用的调试信息,在RTOS的日志打印组件中通常用到了这三个内置宏定义:

  • __FILE__:在源文件中插入当前源文件名;
  • __FUNCTION__: 在源文件中插入当前函数名;
  • __LINE__:在源代码中插入当前源代码行号;

利用这三个宏定义,使用一行代码即可编写一个最简单的日志打印组件

#define DEBUG(format,...) printf("[%s:%05d][%s]"format"rn", __FILE__, __LINE__, __FUNCTION__)

编写一个小程序测试这个仅有一行代码的日志打印组件:

#include <stdio.h>#define DEBUG(format,...) printf("[%s:%05d][%s]"format"rn", __FILE__, __LINE__, __FUNCTION__) int main(void)
{DEBUG("Hello, esay log tools.");return 0;
}

编译运行:

怎么样?所有的信息是不是非常准确?这个仅有一行代码的日志打印组件用起来是不是很爽?

3. RTOS中的完整日志打印组件

当然,一个完整的日志打印组件不能仅仅靠这一行代码来实现,还需要添加很多功能,比如:

  • 设置日志输出等级,区分不同的日志输出;
  • 底层使用自己优化后的printf函数;
  • 添加宏定义控制输出信息是否启用;
  • 添加字符输出颜色控制功能,可与日志输出等级对应;
  • 更多功能,等你探索……

在LiteOS中,日志打印组件底层使用了该内置宏定义功能,源码如下:

#define ATINY_LOG(level, fmt, ...) do { if ((level) >= atiny_get_log_level()) { (void)atiny_printf("[%s][%u][%s:%d] " fmt "rn", atiny_get_log_level_name((level)), (uint32_t)osal_sys_time(), __FUNCTION__, __LINE__, ##__VA_ARGS__); } } while (0)
#else
#define ATINY_LOG(level, fmt, ...)
#endif

而在更多时候,该功能被用来迅速的输出系统断言信息,比如在RT-Thread中有这样的一个功能源码:

/* assert for developer. */
#ifdef ULOG_ASSERT_ENABLE#define ULOG_ASSERT(EXPR)                                                 if (!(EXPR))                                                              {                                                                         ulog_output(LOG_LVL_ASSERT, LOG_TAG, RT_TRUE, "(%s) has assert failed at %s:%ld.", #EXPR, __FUNCTION__, __LINE__); ulog_flush();                                                         while (1);                                                            }
#else#define ULOG_ASSERT(EXPR)
#endif

在TencentOS tiny中也有同样的断言功能源码:

#define TOS_ASSERT_AUX(exp, function, line) if (!(exp)) { tos_kprintln("assert failed: %s %dn", function, line); tos_knl_sched_lock(); tos_cpu_int_disable(); while (K_TRUE) { ; } }#define TOS_ASSERT(exp) TOS_ASSERT_AUX(exp, __FUNCTION__, __LINE__)

接收更多精彩文章及资源推送,欢迎订阅我的微信公众号:『mculover666』。

当当网电子书能打印吗_一行代码就能写一个日志打印组件,你信吗?为你揭晓RTOS中日志打印组件的核心相关推荐

  1. 【华为云技术分享】一行代码就能写一个日志打印组件,你信吗?为你揭晓LiteOS中日志打印组件的核心

    1. 做实验引发的思考 在学习LiteOS日志打印组件使用的时候,我记录了一篇博客:atiny_log | LiteOS 物联网操作系统中的日志打印组件使用分享,关于实验的具体内容,请阅读这篇博客. ...

  2. python制作u盘病毒_十行代码--用Python写一个USB病毒!

    大家好,我又回来了. 昨天在上厕所的时候突发奇想,当你把usb插进去的时候,能不能自动执行usb上的程序.查了一下,发现只有windows上可以,具体的大家也可以搜索(搜索关键词usb autorun ...

  3. 用一行代码高效的求一个列表的平方和

    最近看到一个笔试题,考察的都是 Python 中的高阶函数 题目如下:用一行代码高效的求一个列表的平方和(不能用 sum 函数) 分析 1.先将列表中每个值作平方: 立即想到 map 函数,假设列表是 ...

  4. http代码_一行代码就可以实现HTTP文件服务器,他为什么写了150行?

    互联网已经发展了20多年,web技术早已经不是什么新消息,现在更多的程序员讨论的都是web框架,技术框架,高可用框架等.在框架的背后,其实还是要了解最底层的核心内容,比如TCP/IP协议怎么回事,HT ...

  5. datatables 一行数据生成两行_一行代码搞定分组回归

    写 在前面 在目前为止所有小伙伴们向大猫请教过的R问题中,大猫总结了最常遇见同时也是比较难的三个问题,分别是(1)事件研究法:(2)分组回归:(3)滚动回归.事件研究法在第一期中已经讲述,本期我们就来 ...

  6. 灰色的rgb值_一行代码实现图片的灰色效果

    今天是清明节,警笛长鸣,万众默哀.送别英雄,生活继续. 大部分的app配图,今天都是灰色.这种图片的转换在python里非常容易实现.一行代码搞定. 下面是DE8UG上次说个故事:再见VB.你好,精彩 ...

  7. mapbox 修改初始位置_一行代码教你如何随心所欲初始化Bert参数(附Pytorch代码详细解读)...

    微信公众号:NLP从入门到放弃 微信文章在这里(排版更漂亮,但是内置链接不太行,看大家喜欢哪个点哪个看吧): 一行代码带你随心所欲重新初始化bert的参数(附Pytorch代码详细解读)​mp.wei ...

  8. 局域网怎么查看单位摄像头_一行代码,实现多平台文件查看传输!

    几个不错的通过网站传输文件的工具,其实了解python的朋友可能都知道,借助它,只需要输入一行代码,就可以将电脑变成一台服务器,局域网内的任何能上网的工具都能够查看和下载电脑中的文件. 方法很简单,可 ...

  9. 为了提高python代码运行速度和进行_一行代码让你的python运行速度提高100倍

    Python用的好,猪也能飞起来.今天,带大家学习如何让Python飞起来的方法,干货满满哦! python一直被病垢运行速度太慢,但是实际上python的执行效率并不慢,慢的是python用的解释器 ...

最新文章

  1. java io工作机制_深入分析Java I/O 工作机制
  2. ajax提交后立刻刷新,Ajax提交表单页面刷新很快的解决方法
  3. 6.方法(go语言学习笔记)
  4. Spark Shuffle系列-----1. Spark Shuffle与任务调度之间的关系
  5. 前端urldecode 特殊字符处理导致后端无法解析
  6. I/O多路复用技术是什么?
  7. 自然语言处理系列-1.什么是NLP?
  8. tensorflow之regularizer
  9. Data Mining with R
  10. 任务调度的合理性(拓扑排序)
  11. 《简明Python教程》学习笔记
  12. java sql连接代码 sqlserver的jar包
  13. 抖音短视频去水印网址 视频消重后,火山还是鉴别出来了
  14. 求斐波那契数列的特征方程和通项公式
  15. 【Unity】UI面板:倒计时器
  16. 使用windows命令行 启动WeGame
  17. VS Code折腾记 - (4) 常用必备插件推荐【前端】
  18. Matlab算法DSP移植验证,DSP计算机作业 自适应噪声抵消LMS算法Matlab仿真
  19. JAVA实现输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数
  20. Unity - 性能优化 - 包体,内存 - 偏静态资源的优化

热门文章

  1. python处理gzip压缩的http数据 - XII - 博客大巴
  2. Nature封面论文撤稿闹大了,认定首个室温超导体数据存疑!领域大佬尝试复现6次全失败,9位作者集体抗议无效...
  3. 卡巴斯基导致SVN不能正常工作
  4. 量子通信基础知识简介(二)
  5. Android 查看当前应用的线程数是否超限
  6. CCI(Commodity Channel Index顺势指标)指标及其发明人Donald Lambert的前世今生
  7. Ubuntu中搜狗输入法安装和卸载
  8. SVG 入门指南(初学者入门必备)
  9. 扯淡-20220918
  10. RouterOS 固定IP接入上网设置教程(超详细)