ax-log
路径:
os/arceos/modules/axlog类型:库 crate 分层:ArceOS 层 / 日志运行时基础件 版本:0.3.0-preview.3文档依据:Cargo.toml、src/lib.rs
ax-log 是 ArceOS 的日志前端和格式化层。它建立在 log crate 之上,为 no_std 运行时提供统一的打印宏、日志格式和后端接口,并在 std feature 下退化成可直接在主机环境运行的 logger。它属于运行时叶子基础件:不是串口驱动、不是 tracing 框架,也不是完整的观测平台。
架构设计
设计定位
ax-log 的核心设计思路很克制:
- 复用
logcrate 作为上层日志语义,不自造一套新的日志 facade。 - 用
ax-crate-interface定义LogIf,把“时间、CPU ID、任务 ID、字符输出”这些平台相关能力交给外部实现。 - 在打印时自行做串行化,避免多 CPU/多任务日志交叉。
因此,ax-log 解决的是“日志长什么样、如何输出”,不是“设备如何发字符”或“日志如何持久化”。
1.2 核心模块与对象
这个 crate 基本都在 src/lib.rs 中完成:
LogIf:no_std路径下必须由外部实现的接口。Logger:同时实现fmt::Write与log::Log。ColorCode:不同日志级别对应的 ANSI 颜色。ax_print!/ax_println!:不经过log级别过滤的直接输出宏。print_fmt():真正执行串行化输出的低层入口。
1.3 std 与 no_std 双路径
stdfeature 打开时:Logger.write_str()直接走std::print!。- 时间戳使用
chrono::Local::now()。
stdfeature 关闭时:- 所有输出与环境信息都通过
call_interface!(LogIf::...)获取。 - 是否显示 CPU ID / task ID 由
LogIf::current_cpu_id()和current_task_id()返回值决定。
- 所有输出与环境信息都通过
这意味着 ax-log 不是“只能在裸机里用”的模块,它的 host 验证路径也是正式设计的一部分。
1.4 日志输出主线
Logger::log() 的关键流程如下:
源码里的几个细节值得单独强调:
init()会调用log::set_logger(&Logger),并把默认最大级别设成Warn。set_max_level()只做运行时调节;如果上游用了编译期log-level-*feature,这个函数不会改变结果。print_fmt()内部用ax_kspin::SpinNoIrq<()>做串行化,所以它解决的是输出交叉,不是后端缓冲问题。
核心功能
功能概览
- 提供
error!、warn!、info!、debug!、trace!宏的 ArceOS 运行时接入。 - 提供
ax_print!/ax_println!这类不经日志级别过滤的直接输出接口。 - 提供颜色化、带时间戳和可选 CPU/task 元信息的统一日志格式。
使用场景
init()/set_max_level():由ax-runtime/src/lib.rs在系统 bring-up 早期调用。LogIf:由ax_runtime::LogIfImpl实现,背后再转发到ax-hal::console、ax-hal::time、ax-task等模块。print_fmt():被ax-api/src/imp/mod.rs直接使用,作为 API 层输出通道。warn!等宏:被ax-posix-api、ax-task等模块直接调用。
边界说明
ax-log不管理串口、显 示器或控制台设备;它只定义如何把字符串交给后端。ax-log不是 tracing/span 系统,没有结构化事件树。ax-log也不负责日志落盘、远端传输或 ring buffer。
依赖关系
直接依赖
log:标准日志 facade。ax-crate-interface:no_std路径下的后端接口桥。ax-kspin:输出串行化。chrono:只在std下使用。
主要消费者
ax-runtime:初始化 logger 并提供运行时后端实现。ax-api/ax-posix-api:向上层 API 暴露输出与警告能力。starry-kernel:直接复用同一套日志前端。
开发指南
接入方式
[dependencies]
ax-log = { workspace = true }
如果是主机环境验证,可显式开启 std:
[dependencies]
ax-log = { workspace = true, features = ["std"] }
注意事项
- 修改日志格式时,要同时检查
std与no_std两条路径。 - 修改
LogIf契约时,必须同步更新ax_runtime::LogIfImpl这类实现方。 - 修改
print_fmt()锁策略时,要重新评估输出交叉与中断上下文行为。 - 不要把控制台驱动逻辑塞进
ax-log;这层应该继续保持“前端 + glue”的小体量。