Skip to content

Latest commit

 

History

History
192 lines (149 loc) · 8.38 KB

File metadata and controls

192 lines (149 loc) · 8.38 KB

Comix 项目编码规范

本规范用于统一内核代码风格、注释撰写以及项目文件组织,降低维护成本与重构风险。除非特殊说明,遵循 Rust 官方惯例与现有项目结构。新增代码或修改旧代码时请自检是否满足本规范。


1. 注释规范

Comix 项目统一使用中文进行接口和文档注释

1.1 顶层与模块

  • 每个公共模块(mod.rs 或独立文件)使用 //! 释义模块目的、设计取舍和与其它模块的关系。
  • 若模块内部存在不变量(如:页表条目的合法组合、锁使用上下文),必须在模块顶注释中列出。

1.2 Item 文档(函数 / 结构体 / trait)

  • 公共 API(pub)使用 ///,首行简述,后续分段:
    • 参数说明(使用列表 - name: 含义
    • 返回值说明(含错误场景与 errno 或 Result 类型)
    • 时序 / 调用条件(如:只能在关中断状态下调用)
    • 示例(简短,可省略复杂依赖)
  • 私有函数只在非显而易见逻辑时添加行内注释或块注释。

示例:

/// 分配一个物理页并映射到给定虚拟地址
/// 参数:
///     - va: 需要页对齐的虚拟地址
///     - flags: 页权限(必须包含 valid)
/// 返回: Ok(()) 映射成功;Err(MapError::AlreadyMapped) 已存在;其它错误传递上层
/// 安全:调用者必须保证 va 不指向内核保留区域

1.3 Unsafe 块

  • 每个 unsafe {} 上方添加 // SAFETY: 注释,说明:
    • 不变量(如:指针来自经过校验的页框、长度匹配)
    • 为什么执行内存读写 / 汇编 / 寄存器操作是安全的

示例:

// SAFETY: frame_ppn 来自分配器,指向独占页;长度不超过 PAGE_SIZE
unsafe { ptr::copy_nonoverlapping(src, dst, len); }

1.4 汇编文件(.S

  • 每段逻辑前使用注释块(功能、寄存器约定、修改的 CSR)。
  • 保存 / 恢复顺序与 TrapFrame 偏移保持一一对应,偏移推荐通过宏或包含的 .inc 生成(后续重构)。

1.5 行内注释

  • 避免重复“翻译代码”式注释;仅在出现:
    • 魔数(写出来源)
    • 性能 / 内存布局技巧
    • 架构相关细节 时添加解释。

1.6 TODO / FIXME / OPTIMIZE 标签

  • 统一格式:// TODO(tag): 描述,可选 tag(perf / safety / clarity)。
  • 仅保留真正计划处理的项;过期项需清理。

2. 编码规范

2.1 基础风格

  • 使用仓库内 rustfmt.toml,禁止关闭 rustfmt。
  • 不使用 #![allow(clippy::all)];逐步引入 Clippy 规则,局部抑制使用 #[allow(...)] 并注释原因。

2.2 命名

类型 约定
模块 / 文件 全小写,下划线分词(memory_space
结构体 / 枚举 / Trait PascalCase(MemorySpace, TaskState
方法 / 变量 / 函数 snake_case(activate, alloc_frame
常量 / 静态 UPPER_SNAKE_CASE(PAGE_SIZE, STACK_ALIGN_MASK
枚举成员 PascalCase(User, Kernel
泛型参数 单字母或语义化(T, P: PageProvider

2.3 错误处理

  • 系统调用内部返回负 errno(-libc_errno),内核内部使用 Result<T, E>
  • 错误枚举实现 Debug + Display,日志中使用 {:?} 简明输出。
  • 避免滥用 expect / unwrap,除非:
    • 初始化阶段(panic 可接受)
    • 明确不变量已保证(需注释阐明)

2.4 日志与调试

  • 使用统一日志宏(log::info!, log::warn!);禁止直接 println!(除非常早期 boot 阶段)。
  • panic 信息包含:模块名前缀 + 关键上下文("page_table: invalid PTE flags: ...")

2.5 Unsafe 收口

只允许在以下模块 / 场景出现:

  • 页表和地址空间操作(MMU / satp 切换)
  • Trap 与上下文切换(汇编入口、恢复)
  • 用户态内存复制(copy_from_user / copy_to_user
  • 设备 / CSR 访问

其它模块出现 unsafe 需重构或写明合理性。

2.6 并发与锁

  • 中断上下文只允许使用自旋锁;禁止睡眠锁、阻塞操作、内存分配(除预分配池)。
  • 嵌套获取自旋锁必须保持全序(按模块定义顺序)。
  • 避免持锁调用跨模块高层 API;将重入口风险最小化。

2.7 内存与指针

  • 地址使用类型封装(后续重构):VirtAddr, PhysAddr, Ppn, Vpn,禁止滥用裸 usize
  • 指针算术集中在内存管理层;调用者传入长度必须与对象大小匹配。
  • 不在普通逻辑代码里直接对物理地址做 as *mut u8,应通过安全封装函数。

2.8 模式与泛型

  • 优先组合(struct 包含)而非继承 / 深层 trait 对象。
  • trait 用于抽象可替换组件(如:调度器、页分配器),尤其是内核中使用到的全局对象。
  • 不引入复杂宏元编程;保持简单、展开后可读。

2.9 性能考虑

  • 高频路径(调度 / Trap / 页表)避免分配与格式化字符串。
  • 小循环优先手写而非迭代器链;但保持可读性权衡。
  • 不在中断或 Trap 入口打印日志(除致命错误)。

2.10 单元与集成测试

  • tests 模块使用 #[cfg(test)] 内内联。
  • 纯算法(地址计算、映射合并)单元测试;涉及硬件依赖放到后续仿真集成测试。
  • 不在测试中使用不稳定内部 API;暴露小型测试辅助接口。

3. 项目 / 文件组织规范

3.1 分层结构

层级 职责 依赖方向
arch 架构专有:寄存器、Trap、启动、页表格式 不依赖上层
mm 物理/虚拟内存抽象、分配器、地址类型 仅少量架构细节
kernel 调度、任务、系统调用、CPU 管理 依赖 mm + arch
fs / vfs 文件系统与名称解析层 依赖 kernel(任务上下文)
sync 锁与并发原语 不依赖高层
log 日志设施 不依赖高层
user(嵌入) 用户态程序二进制 不参与编译逻辑

禁止反向依赖:高层不得让底层引用其内部结构(例:mm 不应引用 Task)。

3.2 目录与文件

  • arch 模块外,采用扁平化的组织方式,mod路径不超过三层(例如,`crate::kernel::task)。
  • 过大的模块单独使用一个 mod.rs 汇总导出公共接口。
  • 文件命名语义化:trap_handler.rs, frame_allocator.rs, task_manager.rs
  • 超过 ~800 行的文件需拆分(例如:页表操作与入口管理)。
  • 宏放置:单独 macros.rs 或靠近使用处,避免全局污染。

3.3 架构扩展

  • arch/<isa>/ 子目录结构与 riscv 保持一致(trap、mm、platform)。
  • 公共抽象(如:PageTableOps)放在非架构目录,RISC-V 提供实现。

3.4 常量与配置

  • 架构相关常量置于 arch/riscv/constant.rs
  • 全局可调参数集中到 config.rs,避免散落硬编码。
  • 不允许多处定义同一页大小 / 对齐值。

3.5 构建脚本与工具

  • 后续生成 TrapFrame 偏移可使用 build.rs 输出 const,防止汇编与 Rust 偏移不一致。
  • QEMU 启动脚本单一入口(qemu-run.sh),Makefile 封装常用目标:run / debug / gdb / fmt / clippy.

3.6 依赖控制

  • 避免引入重量级依赖(serde / alloc-heavy crates),保持可控二进制大小与可审计。

3.7 提交流程

  • 单次提交聚焦单一主题(“实现 syscall write 参数校验”)。
  • 提交信息格式:
    • 前缀:feaf: ... / test: ... / docd: ...
    • 主体:简述改动与动机,列出兼容性注意点。

4. 安全与不变量(核心摘录)

领域 不变量
页表 映射条目 valid ⇒ 物理页独占或引用计数递增;U 页不可被内核写入除非 SUM=1
Trap sscratch 始终指向当前任务 TrapFrame;kernel_sp 有效可写
调度 任务状态转移遵循:Ready → Running → {Blocked
内存复制 用户指针必须通过边界检查(地址区间 + 页权限),失败返回 -EFAULT

5. 附录:常量命名示例

常量 说明
PAGE_SIZE 页大小(与架构一致)
STACK_ALIGN_MASK 栈对齐掩码
KERNEL_BASE 内核虚拟地址基址(若使用高半区)
USER_STACK_SIZE 默认用户栈大小

本规范将随项目演进更新,新增模块请在 PR 中引用本文件并补充相关规则。欢迎提出改进建议。