os/log/
mod.rs

1//! 内核日志子系统
2//!
3//! 该模块提供了一个类似 **Linux 内核风格的日志系统**,并在裸机环境中实现了**无锁环形缓冲区**。
4//!
5//! # 组件
6//!
7//! - [`buffer`] - 用于日志存储的无锁环形缓冲区
8//! - [`config`] - 配置常量(缓冲区大小、消息长度限制)
9//! - [`context`] - 上下文信息收集(CPU ID、任务 ID、时间戳)
10//! - [`log_core`] - 核心日志实现 (LogCore)
11//! - [`entry`] - 日志条目结构和序列化
12//! - [`level`] - 日志级别定义(从 Emergency 到 Debug)
13//! - [`macros`] - 面向用户的日志宏 (`pr_info!`, `pr_err!`, 等)
14//!
15//! # 设计概览
16//!
17//! ## 双输出策略
18//!
19//! 日志系统采用两层方法:
20//!
21//! 1. **即时控制台输出**:达到控制台级别阈值(默认:Warning 及以上)的日志会**直接打印到控制台**,以实现紧急可见性。
22//! 2. **环形缓冲区存储**:所有达到全局级别阈值(默认:Info 及以上)的日志都会被写入**无锁环形缓冲区**,用于异步消费或事后分析。
23//!
24//! ## 性能特点
25//!
26//! - **无锁并发**:使用原子操作(fetch_add, CAS)而非互斥锁,支持多生产者日志记录而**不会阻塞**。
27//! - **早期过滤**:日志级别检查在宏展开时发生,避免对禁用级别的日志进行格式化字符串评估。
28//! - **固定大小分配**:**没有动态内存分配**;所有结构体使用编译时已知的大小,适用于裸机环境。
29//! - **缓存优化**:读写器数据结构经过缓存行填充(64 字节),以防止多核系统上的**伪共享**。
30//! - **尽可能零拷贝**:在可行的情况下,日志条目是**就地构造**的,以最大限度地减少内存操作。
31//!
32//! ## 架构特定集成
33//!
34//! 日志系统与架构特定组件集成:
35//!
36//! - **定时器**:通过 `arch::timer::get_time()` 收集时间戳
37//! - **控制台**:通过 `console::Stdout` 输出(通常是 UART)
38//! - **CPU ID**:通过 `arch::kernel::cpu::cpu_id()` 获取当前 CPU ID
39//! - **任务 ID**:通过 `kernel::cpu::current_cpu()` 获取当前任务的 tid(若无任务则为 0)
40//!
41//! # 使用示例
42//!
43//! ```rust
44//! use crate::log::*;
45//!
46//! // 基本日志记录
47//! pr_info!("内核已初始化");
48//! pr_err!("分配 {} 字节失败", size);
49//!
50//! // 配置日志级别
51//! set_global_level(LogLevel::Debug);  // 记录所有级别
52//! set_console_level(LogLevel::Error); // 只打印错误及以上的级别
53//!
54//! // 读取缓冲的日志
55//! while let Some(entry) = read_log() {
56//!     // 处理日志条目
57//! }
58//! ```
59
60#![allow(unused)]
61mod buffer;
62mod config;
63mod context;
64mod entry;
65mod level;
66mod log_core;
67pub mod macros;
68
69pub use config::{
70    DEFAULT_CONSOLE_LEVEL, DEFAULT_LOG_LEVEL, GLOBAL_LOG_BUFFER_SIZE, MAX_LOG_MESSAGE_LENGTH,
71};
72pub use entry::LogEntry;
73pub use level::LogLevel;
74pub use log_core::format_log_entry;
75
76// ========== 全局单例 ==========
77
78/// 全局日志系统实例
79///
80/// 使用 const fn 在编译时初始化,零运行时开销。
81/// 所有日志宏和公共 API 都委托给此实例。
82static GLOBAL_LOG: log_core::LogCore = log_core::LogCore::default();
83
84// ========== 公共 API (精简封装) ==========
85
86/// 核心日志实现(由宏调用)
87#[doc(hidden)]
88pub fn log_impl(level: LogLevel, args: core::fmt::Arguments) {
89    GLOBAL_LOG._log(level, args);
90}
91
92/// 检查日志级别是否启用(由宏调用)
93#[doc(hidden)]
94pub fn is_level_enabled(level: LogLevel) -> bool {
95    level as u8 <= GLOBAL_LOG._get_global_level() as u8
96}
97
98/// 从缓冲区读取下一个日志条目
99pub fn read_log() -> Option<LogEntry> {
100    GLOBAL_LOG._read_log()
101}
102
103/// 非破坏性读取:按索引 peek 日志条目,不移动读指针
104pub fn peek_log(index: usize) -> Option<LogEntry> {
105    GLOBAL_LOG._peek_log(index)
106}
107
108/// 获取当前可读取的起始索引
109pub fn log_reader_index() -> usize {
110    GLOBAL_LOG._log_reader_index()
111}
112
113/// 获取当前写入位置
114pub fn log_writer_index() -> usize {
115    GLOBAL_LOG._log_writer_index()
116}
117
118/// 返回未读日志条目的数量
119pub fn log_len() -> usize {
120    GLOBAL_LOG._log_len()
121}
122
123/// 返回未读日志的总字节数(格式化后)
124pub fn log_unread_bytes() -> usize {
125    GLOBAL_LOG._log_unread_bytes()
126}
127
128/// 返回已丢弃日志的计数
129pub fn log_dropped_count() -> usize {
130    GLOBAL_LOG._log_dropped_count()
131}
132
133/// 设置全局日志级别阈值
134pub fn set_global_level(level: LogLevel) {
135    GLOBAL_LOG._set_global_level(level);
136}
137
138/// 获取当前全局日志级别
139pub fn get_global_level() -> LogLevel {
140    GLOBAL_LOG._get_global_level()
141}
142
143/// 设置控制台输出级别阈值
144pub fn set_console_level(level: LogLevel) {
145    GLOBAL_LOG._set_console_level(level);
146}
147
148/// 获取当前控制台输出级别
149pub fn get_console_level() -> LogLevel {
150    GLOBAL_LOG._get_console_level()
151}
152
153// ========== 测试模块 ==========
154#[cfg(test)]
155mod tests;