You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust no_std环境下日志宏alloc格式化无输出问题排查

自定义Rust no_std内核日志系统问题排查与修复

问题概述

在自定义Rust no_std内核环境中,实现了基于alloc::format!的日志系统,期望通过LOGGER.trigger()输出缓存的日志,但存在以下问题:

  • 移除log!宏内的调试println_serial!后,无任何日志输出
  • 调用LOGGER.trigger()无法取出并输出缓存的日志
  • 希望log!宏支持{:?}等Debug格式化语法

核心问题分析

  1. 环形缓冲区逻辑错误:原CircularBuffer的pop_front和increment_tail实现存在逻辑缺陷,导致日志无法正确从缓冲区取出
  2. Debug格式化支持缺失:部分核心类型未实现Debug trait,导致alloc::format!无法处理{:?}语法
  3. 初始化依赖问题:Logger未初始化时调用get_verbosity会触发panic,导致日志代码被跳过

修复方案

1. 修复环形缓冲区实现

原环形缓冲区用tail=N+1标记满状态的逻辑存在歧义,改为用count记录元素数量,简化满/空判断逻辑:

use core::mem::MaybeUninit;

use thiserror_no_std::Error;

#[derive(Error, Debug)]
#[error("Failed to push item into buffer")]
pub struct PushError;

pub struct CircularBuffer<T, const N: usize> {
    array: [MaybeUninit<T>; N],
    head: usize,
    tail: usize,
    count: usize,
}

impl<T, const N: usize> CircularBuffer<T, N> {
    pub const fn new() -> Self {
        Self {
            array: MaybeUninit::uninit_array(),
            head: 0,
            tail: 0,
            count: 0,
        }
    }

    pub fn push_back(&mut self, item: T) -> Result<(), PushError> {
        if self.count >= N {
            return Err(PushError);
        }

        self.array[self.tail] = MaybeUninit::new(item);
        self.tail = (self.tail + 1) % N;
        self.count += 1;
        Ok(())
    }

    pub fn pop_front(&mut self) -> Option<T> {
        if self.count == 0 {
            return None;
        }

        let item = unsafe { self.array[self.head].assume_init_read() };
        self.head = (self.head + 1) % N;
        self.count -= 1;
        Some(item)
    }
}

2. 添加Debug格式化支持

为核心类型实现Debug trait,确保alloc::format!支持{:?}语法:

// 在Verbosity枚举中添加Debug derive
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug)]
pub enum Verbosity {
    Debug,
    Info,
    Warning,
    Error,
}

// 在Log结构体中添加Debug derive
#[derive(Debug)]
pub struct Log {
    pub file: &'static str,
    pub line: u32,
    pub verbosity: Verbosity,
    pub message: String,
}

3. 优化Logger初始化容错逻辑

修改get_verbosity方法,避免未初始化时触发panic,确保日志能正常推送:

pub fn get_verbosity(&self, module: &str) -> Verbosity {
    self.verbose
        .lock()
        .as_ref()
        .and_then(|map| map.get(module))
        .copied()
        .unwrap_or(Verbosity::Info)
}

4. 确保Logger正确初始化

在内核启动阶段调用logger::init(),传入模块级别配置:

// 示例初始化代码
use crate::logger::{init, Verbosity};
use hashbrown::HashMap;

fn kernel_main() {
    let mut verbose_config = HashMap::new();
    verbose_config.insert("kernel".to_string(), Verbosity::Debug);
    init(verbose_config);

    // 测试日志
    log!(Verbosity::Debug, "Debug message with {:?}", 42);
    log!(Verbosity::Info, "Info message");

    // 触发日志输出
    crate::logger::trigger();
}

验证修复

修复后:

  • 调用log!宏会将日志正确缓存到环形缓冲区
  • 调用trigger()会取出所有缓存日志并通过println_serial!输出
  • 支持使用{:?}格式化实现了Debug trait的类型

内容的提问来源于stack exchange,提问作者Saurav Maheshkar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:52:03