openvela——动态管理日志输出通道及其实现原理

《Vela rpmsg log 实现原理》中提到 vela 日志输出支持多通道日志输出,它们是在系统运行前期配置好的,所以无法将它们动态删除。但是可以控制使能、禁用某通道,达到相应通道输出、不输出日志的目的。接下来篇章将讲述"动态管理日志输出通道方法"和"动态管理日志输出通道原理"。

动态管理日志输出通道方法

  • 列出当前已配置的所有输出通道及它们各自的状态

    在 nuttx shell 中执行setlogmask list命令,输出 "通道":"状态" 格式的信息。如下结果显示:"default 通道"(物理串口)已打开、"ramlog 通道" 已打开。

bash 复制代码
ap> setlogmask list
Channels:
  default: enable
  ramlog: enable
  • 禁用(启用)日志输出通道
bash 复制代码
ap> setlogmask disable default 
ap> setlogmask enable default 

动态管理日志输出通道原理

从代码角度来看禁止某(些)通道输出日志的方式是在写日志时候跳过禁用通道,如下代码片段:

cpp 复制代码
ssize_t syslog_write_foreach(FAR const char *buffer,
                             size_t buflen, bool force)
{
  //...

  for (i = 0; i < CONFIG_SYSLOG_MAX_CHANNELS; i++) {
      FAR syslog_channel_t *channel = g_syslog_channel[i];

      if (channel == NULL) break;

#ifdef CONFIG_SYSLOG_IOCTL
    /// 根据"禁用"状态,忽略写相应通道
      if (channel->sc_state & SYSLOG_CHANNEL_DISABLE)
          continue;
#endif
    /// ...
    /// 调用通道的写函数
    }
}

命令 setlogmask enable(disable) out_channel_name 的本质是:修改对应通道变量的 sc_state。为了实现此目的:

  1. Vela 注册了一个虚拟设备,生成一个设备节点------"/dev/log";

  2. setlogmask 命令会打开此设备并通过ioctl调用传递命令参数;

  3. sys log 驱动的 syslog_chardev_ioctl 接收到命令参数后,进行名字匹配找到对应通道变量并更新sc_state。

cpp 复制代码
int main(int argc, FAR char *argv[])
{
  if (argc < 2)
    {
      show_usage(argv[0], EXIT_FAILURE);
    }

#ifdef CONFIG_SYSLOG_IOCTL
  if (strcmp(argv[1], "list") == 0)
    {
      print_channels();
      return EXIT_SUCCESS;
    }
  else if (argc == 3)
    {
      if (strcmp(argv[1], "enable") == 0)
        {
          return disable_channel(argv[2], false);
        }
      else if (strcmp(argv[1], "disable") == 0)
        {
          return disable_channel(argv[2], true);
        }
      else
        {
          show_usage(argv[0], EXIT_FAILURE);
        }
    }
#endif
cpp 复制代码
static int disable_channel(FAR const char *name, bool disable)
{
  fd = open("/dev/log", O_WRONLY);

  info.sc_disable = disable;
  strlcpy(info.sc_name, name, sizeof(info.sc_name));
  ret = ioctl(fd, SYSLOGIOC_SETFILTER, (unsigned long)&info);
  
  close(fd);
  
  return ret;
}
cpp 复制代码
#ifdef CONFIG_SYSLOG_IOCTL
static int syslog_chardev_ioctl(FAR struct file *filep,
                                int cmd, unsigned long arg)
{
  if (cmd == SYSLOGIOC_GETCHANNELS) {
      // ...
  } else if (cmd == SYSLOGIOC_SETFILTER) {
      info = (FAR struct syslog_channel_info_s *)arg;

      for (i = 0; i < CONFIG_SYSLOG_MAX_CHANNELS; i++)
        {
          if (strncmp(g_syslog_channel[i]->sc_name, info->sc_name,
                      sizeof(info->sc_name)) == 0)
            {
              channel = g_syslog_channel[i];
              break;
            }
        }
      // ...

      // 修改日志输出状态
      channel->sc_state = info->sc_disable ?
                          channel->sc_state | SYSLOG_CHANNEL_DISABLE :
                          channel->sc_state & ~SYSLOG_CHANNEL_DISABLE;
    }

  return OK;
}
#endif
相关推荐
开源武术4 天前
使用 J-Link GDB 插件增强 openvela 线程调试
openvela
开源武术14 天前
openvela 使用 _FORTIFY_SOURCE 增强 C 语言内存安全性
openvela
开源武术2 个月前
openvela 使用 VSCode 调试 SIM 环境
openvela
自由的晚风7 个月前
基于小米Open-Vela开源系统的高级计算器实现 | 支持C++数学函数与 LVGL UI
经验分享·物联网·开源·嵌入式·小米·nuttx·openvela
byte轻骑兵1 年前
OpenVela——专为AIoT领域打造的开源操作系统
开源·openvela
一只搬砖的猹1 年前
小米vela系统(基于开源nuttx内核)——openvela开源项目
linux·开源·小米·rtos·nuttx·openvela·apache2.0