SylixOS 日志子系统实现分析

SylixOS 日志子系统实现分析

Q:SylixOS 日志子系统实现分析
SylixOS 中日志系统的相关实现在目录“/libsylixos/SylixOS/system/logLib”下。

1、内核中日志系统初始化      

系统内核启动时候调用到 _logInit 函数,函数实现如下:
(1)创建消息队列;
(2)调用函数 API_PartitionCreate 创建内存分区(建立 printk 缓冲);
(3)建立 LOG 处理线程 t_log 并初始化。

2、分析

2.1 t_log 线程分析

(1) 调用函数 API_MsgQueueReceive 从消息队列接收消息;
      
(2)判断是任务中发送,还是中断中发送,根据是否打印头部的参数,选择是否打印头部信息;
      
(3)调用函数 __logPrintk 或者 __logPrintf 打印数据;
      
(4)更新 _G_iLogMsgsLost 值,即丢失的 log 消息数量。

2.2 _logPrintk 函数分析

功能:向指定的文件集打印 LOG 信息。
      
执行流程:

(1)判断打印级别,若大于 console_loglevel 则不打印信息。
      
(2)检查所有可执行读操作的文件,调用 write 函数打印数据。

2.3 _logPrintf 函数分析

功能:向指定的文件集打印 LOG 信息。
      
执行流程:
      
(1)调用函数 bnprintf 格式化字符串;
      
(2)检查所有可执行读操作的文件,调用 write 函数打印数据。

3、bspInit.c 文件中日志系统相关初始化

3.1 设置 printk 打印信息等级

console_loglevel 默认值为7;

在 bspInit.c 中初始化时候设置 console_loglevel 值为4,设置代码如下:
  1. console_loglevel = default_message_loglevel;         /*  设置 printk 打印信息等级     */

3.2 halLogInit 函数初始化目标系统日志系统
  1. FD_ZERO(&fdLog);
  2. FD_SET(STD_OUT, &fdLog);
  3. API_LogFdSet(STD_OUT + 1, &fdLog);                          /*  初始化日志                         */
调用函数 API_LogFdSet 设置日志系统需要关心的文件描述符。

4、日志系统提供的保存日志信息的函数

4.1 API_LogPrintk 函数  

驱动或者内核常用的日志打印函数 printk,即等价于函数 API_LogPrintk。
  1. #define printk           API_LogPrintk
    
 函数执行过程:
(1 )解析输入字符串中的打印等级,如果有则设置解析值为打印级别,若没有则设置为默认级别,即 default_message_loglevel;
(2)判断打印级别,若大于 console_loglevel 则不打印信息;
(3)调用 c 库函数 vsnprintf 向字符串中打印自定义数据格式;
(4)填充消息结构体中其余成员参数;
(5)判断 log 系统是否初始化,如果没有初始化则调用函数 __logBspMsg 打印信息;若初始化完成,则调用 API_MsgQueueSend 函数向消息队列发送消息,发送失败则增加丢失消息队列计数值,即 _G_iLogMsgsLost 值。
由函数执行过程可以看出,printk 函数本质上是将需要打印的数据保存到消息中,以消息队列的方式发送出去,由“t_log”线程接收消息队列中的消息,然后执行打印操作。

4.2 API_LogMsg函数

API_LogMsg 函数的功能和 API_LogPrintk 函数类似,都是用来记录格式化日志信息。
区别在于:
(1 )API_LogMsg 函数输入参数格式是定长的,而 API_LogPrintk 函数输入参数格式是变长字符串。
(2)调用 API_LogMsg 函数发送的消息,“t_log”中最后会调用 __logPrintf 函数打印数据;
          而调用 API_LogPrintk 函数发送的消息,“t_log”中最后会调用 __logPrintk 函数打印数据;

5、相关Shell命令    

  1. logfiles 显示内核日志打印文件列表
  2. logfileclear 从内核日志打印文件表中清除指定的内核文件描述符
  3. logfileadd  向内核日志打印函数加入指定的内核文件描述符
  4. loglevel  显示或设置当前内核日志(printk)打印等级
根据以上 Shell 命令,同时构建测试程序,演示 printk 函数向文件描述符中输出日志信息的例子:

6、总结

SylixOS日志子系统主要功能是记录系统发生的各个事件,根据不同的日志等级选择是否打印信息;根据API_LogFdSet设置日志系统输出的文件集。

测试程序代码、测试过程详见:

    • Related Articles

    • SylixOS 日志子系统实现示例

      Q:SylixOS 日志子系统实现示例 (1)测试程序代码如下: #include <stdio.h> #include "system/loglib/loglib.h" int main (int argc, char **argv) { console_loglevel = default_message_loglevel;  int __unused i; for (i = 1; i < 20; i++) {     usleep (10000);     ...
    • An error occurred.See error log for more details.

      问:  如何解决 IDE 在编译点选工程的时候出现 An error occurred.See error log for more details. 的问题。 解决方式: 删除工作目录下的 .metadata 后重新打开 IDE 编译 可以正常使用。 参考文章:IDE 工程出现在属性页面不能修改参数
    • SylixOS 功能介绍及版本差异

      SylixOS功能介绍及版本差异 SylixOS 标准版 SylixOS 标准版是 SylixOS 的基础版本,具备如下功能: 兼容 IEEE 1003(ISO/IEC 9945)操作系统接口规范; 兼容 POSIX 1003.1b(ISO/IEC 9945-1)实时编程标准; 支持国军标 GJB7714-2012 操作系统接口规范; 优秀的实时性能(任务调度与切换算法时间复杂度为 O(1)); 支持无限多任务; 抢占式调度支持 256 个优先级; 支持虚拟进程; ...
    • SylixOS lite 版—基于 STM32F767 资源使用情况

      1、基本概念     代码段(text):顾名思义,代码存放的位置,在 STM32 中代码段一般存放于内置 FLASH 中; 已初始化数据段(data):已初始化数据段会分别体现在 FlASH 中和 RAM 中。因为是全局变量,运行过程中需要进行读写操作,因此占用一段 RAM 空间。又因为有初始值,其初始值需要占用 FlASH 空间。   未初始化的数据段(bss):bss 与 data 相同的地方时它也是全局变量,运行过程中需要进行读写操作,因此占用一段 RAM ...
    • error: xxx-sylixos-elf-lzocom.exe

      Q:IDE 在编译工程时出现:xxxx-sylixos-elf-lzocom.exe  应用程序出错。 应用程序无法正常启动(0xc000007b)。请单击“确定”关闭应用程序。信息如下图所示。 安装 vc2010_redist_x86.exe 即可解决此问题, 此文件在 IDE 软件安装包的 Tools 目录下(如 SylixOS IDE 3.9.11_professional\Tools) 。