查看: 20806|回复: 5

清风徐来——Zephyr实战篇(7)之log系统

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3300

    主题

    6547

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32030
    最后登录
    2024-4-26
    发表于 2022-3-17 09:55:48 | 显示全部楼层 |阅读模式
    清风徐来——Zephyr实战篇(7)之log系统

    在正式开篇之前,先抛出一个问题,大家认为对于系统开发而言什么是最重要的?小编认为是调试信息,因为调试信息可以让我们了解当前系统中程序的运行状态,并将其显示出来,让我们能够按图索骥,尤其在出现问题时,能够精准定位。


    那么本期,小编要和大家聊聊Zephyr中的log系统,没错,Zephyr中包含了一个非常强大的log系统。一般log的输出往往会占用一定的CPU时间,从而对程序逻辑产生影响,导致不可预期的后果。


    而在Zephyr中,依赖于log缓冲区的存在,几乎不会占用当前程序上下文执行时间,log信息会被首先缓存到缓存区,然后当系统空闲时,这些数据才会被输出到后端通信设备(例如串口,网络等)。


    下面我们来具体看下ZephyrOS中log系统的一些特点。


    异步显示能力,不占用当前上下文时间
    模块级log信息管理
    同模块中多实例
    同时支持编译时和运行时的log信息过滤
    信息时间戳
    多显示后端支持,目前共支持9种不同的后端:
    14.png
    Log系统的组成
    Zephyr的log系统由三部分构成,分别是:


    1. 前端API:主要用于modules/system中,包括但不限于:
    log模块的注册和声明
    log级别设置
    不同类型信息显示,包括error,warning,info, debug messages以及hexdump
    模块不同实例定义与注册
    2. log核心:负责管理已经注册的log模块和实例化对象,将log信息分发到不同的后端以进行显示


    3. 后端:log显示终端,提供不同的log信息显示策略


    如图所示,为Zephyr的log系统的一个总体架构示意图,首先通过前端API进行log模块的注册和初始化,添加log信息,随后log core将这些信息分发到不同的显示后端中进行显示:
    15.png
    Log系统的管理
    我们的log系统如何进行管理呢?当然了,既然是在ZephyrOS中,一定是通过Kconfig选项进行控制了,其中包括:


    1. 过滤支持(subsys/logging/Kconfig.filtering):
    CONFIG_LOG_RUNTIME_FILTERING : 支持运行期动态调整
    CONFIG_LOG_DEFAULT_LEVEL : 默认系统log级别(0-4)
    CONFIG_LOG_OVERRIDE_LEVEL : 全局配置最小log级别,针对所有注册的log模块
    CONFIG_LOG_MAX_LEVEL : 全局配置最大log级别,针对所有注册的log模块
    2. log打印模式(subsys/logging/Kconfig.mode):
    CONFIG_LOG_MODE_DEFERRED : log信息会被缓存,稍后处理
    CONFIG_LOG_MODE_IMMEDIATE : log信息会立刻被处理,当然,会影响当前上下文代码的执行
    CONFIG_LOG_MODE_MINIMAL : log系统的最小实现


    3. 处理过程(subsys/logging/Kconfig.processing)
    CONFIG_LOG_PRINTK : log信息直接被打印
    CONFIG_LOG_MODE_OVERFLOW : 当log缓存满了之后,丢掉老的log信息
    CONFIG_LOG_BLOCK_ IN_THREAD : 当log缓存满了之后,log系统会被阻塞
    4. 格式化(subsys/logging/Kconfig.formatting)
    CONFIG_LOG_IMMEDIATE_CLEAN_OUTPUT : 在log信息处理时插入中断锁,保证处理过程不会被打断
    CONFIG_LOG_BACKEND_SHOW_COLOR : 红色代表error,红色代表warning

    Log模块的定义
    那么如何定义一个log模块呢?很简单,每一个模块子系统只需要调用LOG_MODULE_REGISTER()即可完成log模块的声明,并将其注册到log系统中。


    但是,这里有个需要注意的地方,如果一个模块包含多个文件,这些额外的文件需要使用LOG_MODULE_DECLARE()来声明。看一个简单的例子:
    1. #include <zephyr.h>
    2. #include <logging/log.h>
    3. LOG_MODULE_REGISTER(MODULE_NAME, CONFIG_MY_MODULE_LOG_LEVEL);
    4. const char *sample_module_name_get(void)
    5. {
    6.     return STRINGIFY(MODULE_NAME);
    7. }
    8. void sample_module_func(void)
    9. {
    10.     LOG_INF("log in test_module %d", 11);
    11. }
    复制代码
    这里的CONFIG_MY_MODULE_LOG_LEVEL需要通过kconfig文件进行定义,而如果我们不显式定义这个LEVEL的话,比如我们可以使用LOG_MODULE_REGISTER(MODULE_NAME)来完成同样的log模块的注册,只不过会使用缺省的CONFIG_LOG_DEFAULT_LEVEL作为log模块级别。
    Log模块的级别定义
    Zephyr的log系统定义了5个级别,分别是:
    ·LOG_LEVEL_NONE : 0U
    ·LOG_LEVEL_ERR : 1U
    ·LOG_LEVEL_WRN : 2U
    ·LOG_LEVEL_INF : 3U
    ·LOG_LEVEL_DBG : 4U
    同样的,Zephyr提供了对应级别的log打印函数:


    ·LOG_ERR(…), LOG_HEXDUMP_ERR(_data, _length, _str)
    ·LOG_WRN(…), LOG_HEXDUMP_WRN(_data, _length, _str)
    ·LOG_INF(…), LOG_HEXDUMP_WRN(_data, _length, _str)
    ·LOG_DBG(…), LOG_HEXDUMP_WRN(_data, _length, _str)


    这样一来,我们就可以直接调用相应的宏,进行不同级别的log信息打印。


    当然,如果我们在定义log模块时候,定义了模块log级别为LOG_LEVEL_NONE,相当于禁止了log功能,不会有任何log信息打印出来,这样一来也就实现了编译期模块级的log级别过滤。

    Log信息的过滤
    那么怎么实现运行期间的log信息过滤呢?


    先需要定义CONFIG_LOG_RUNTIME_FILTERING=y使能运行期过滤。但是,需要注意,这样一来会提高RAM/FLASH的使用量,因此在使用时,需要权衡考虑。


    同时,为了实现运行期控制,需要使能shell,log模块的定义方法与静态方法一致,只不过,我们现在可以在控制台通过shell指令进行动态控制,假设我们通过LOG_MODULE_REGISTER(myapp)定义了一个叫myapp的模块,那么我们就可以:
    ·log enable inf myapp
    ·log disable
    ·log enable err
    ·log list_backends
    ·log status
    其中,log status是一条很有用的指令,可以列出当前注册到log系统中的所有log模块,包括他们当前的过滤级别以及他们的固有(编译期指定)的过滤级别。

    Log系统对性能的影响
    最后我们来看下,log系统的使能对系统的影响。


    首先毋庸置疑的是,log系统的添加提供了很多有用的调试信息,但是万物都有两面性:
    ·ram/flash的额外占用
    ·时序影响(尤其是当log打印与程序的执行在同一个上下文中时)
    下面是不同的配置对系统ram/flash占用的影响,差别还是很明显的:
    16.png
    好了,今天小编就给大家介绍到这儿了,主要和大家分享了Zephyr中的log系统,以及如何创建一个我们自己的log模块并通过shell动态设置log显示级别,以实现运行期的log信息过滤。我们下期见。


    签到签到
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    7 小时前
  • 签到天数: 1940 天

    [LV.Master]伴坛终老

    61

    主题

    1万

    帖子

    3

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    17296
    最后登录
    2024-4-26
    发表于 2022-3-17 10:22:16 | 显示全部楼层
    来学习学习
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    4 小时前
  • 签到天数: 839 天

    [LV.10]以坛为家III

    5

    主题

    5711

    帖子

    1

    金牌会员

    Rank: 6Rank: 6

    积分
    6943
    最后登录
    2024-4-26
    发表于 2022-3-17 10:25:12 | 显示全部楼层
    Zephyr实战篇学习
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    昨天 21:19
  • 签到天数: 1210 天

    [LV.10]以坛为家III

    22

    主题

    4763

    帖子

    0

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    8083

    活跃会员

    最后登录
    2024-4-26
    发表于 2022-3-17 11:07:38 | 显示全部楼层
    一转眼都第七篇了
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    8 小时前
  • 签到天数: 1479 天

    [LV.10]以坛为家III

    203

    主题

    2万

    帖子

    64

    超级版主

    Rank: 8Rank: 8

    积分
    92624
    最后登录
    2024-4-26
    发表于 2022-3-17 21:59:58 | 显示全部楼层
    感谢管管分享,都可以成一个系列了~·
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    2

    帖子

    0

    新手上路

    Rank: 1

    积分
    3
    最后登录
    2022-4-15
    发表于 2022-4-15 15:27:47 | 显示全部楼层
    不错,希望弄个实例贯穿一下整个过程。
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-26 18:34 , Processed in 0.132820 second(s), 27 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表