Tock Core Notes 2021-04-23 解读:Tock 2.0 收官期的错误码规范与 Upcall 防交换机制

发布时间:2026/10/12 1:37:20
Tock Core Notes 2021-04-23 解读:Tock 2.0 收官期的错误码规范与 Upcall 防交换机制 操作系统嵌入式嵌入式OS【免费下载链接】tockA secure embedded operating system for microcontrollers项目地址https://gitcode.com/gh_mirrors/to/tock点击查看免费下载本文以 Tock 操作系统核心团队 2021 年 4 月 23 日的例会纪要doc/wg/core/notes/core-notes-2021-04-23.md为主线解读 Tock 2.0 发布前夜团队围绕 HIL 错误码规范化、系统调用返回值语义、kernel crate 导出重组与「阻止 Upcall 交换」机制所做出的关键决策。结合当前仓库源码读者可以清晰看到这些设计讨论最终如何在 kernel/src/errorcode.rs、kernel/src/syscall.rs、kernel/src/grant.rs 等核心文件中落地成型。会议概况2.0 发布前的收官讨论本次例会由 Tock 核心团队 9 位成员参加Hudson Ayers、Brad Campbell、Branden Ghena、Philip Levis、Gabriel Marcano、Pat Pannuto、Leon Schuermann、Vadim Sukhomlinov、Johnathan Van Why议程集中在三个方向会前更新Tockloader 修复、内核二进制代码体积研究、HIL TRDHardware Interface Layer 技术报告错误码条款修订Tock 2.0 状态更新系统调用 TRD 引入BADRVAL、ReturnCode向StatusCode迁移、kernel crate 导出重组、AppSlice 别名安全性问题阻止 Upcall 交换将全部非虚拟化 capsule 迁移到 Grant 机制从根源上杜绝 upcall 被非法替换。对照今日仓库kernel/src/lib.rs中KERNEL_MAJOR_VERSION 2kernel/src/lib.rs说明这次会议所规划的 2.0 目标最终如期达成会议中讨论的多数机制至今仍在内核中发挥核心作用。会前更新三件与工程质量直接相关的事Tockloader 修复与发布前测试Brad 汇报了 Tockloader 的几项小修复此前程序退出时可能抛出异常疑似仅发生在 macOS 上已在最新 Git HEAD 修复但正式发布前仍需更多测试以防止新问题引入。Tockloader 是 Tock 生态中负责向开发板刷写内核与应用的配套工具这类「退出时异常」问题虽不直接影响内核运行却会干扰开发者正常的刷写与调试流程。内核代码体积研究inlining 与 debug 语句的开销Phil 提到有学生在研究内核二进制体积实验方法是通过调整函数内联inlining来分解各函数的体积成本下一步计划量化「移除全部调试语句」对体积的影响。Leon 随即提出一个具有实际价值的诉求希望研究结果能持续反馈到 Tock 2.0 发布前的二进制尺寸调优中而非等到报告最终成型才一次性公开。从当前仓库看Tock 对二进制体积与内存占用的关注延续至今tools/目录下保留了 print_tock_memory_usage.py、diff_memory_usage.py 等内存占用分析工具并在 CI 中用于跟踪每次改动带来的尺寸变化——这正是该议题沉淀下来的工程实践。HIL TRD 修订回调错误码统一为 ErrorCodePhil 提交了对 HIL TRD 的更新对应 PR #2550。修订的背景是文档内部存在矛盾一方面声称回调必须返回ErrorCode另一方面又允许 HIL 定义自己的错误类型如 I2C 的例子。修改后的文本将措辞统一为回调应当SHOULD返回ErrorCode无论错误是作为回调的一部分返回还是同步返回类型应当保持一致。这一修订在今日源码中可以得到直接印证。标准错误码集中定义于 kernel/src/errorcode.rs每个错误码对应固定的usize非零数值0保留给「无错误/成功」FAIL 1, BUSY 2, ALREADY 3, OFF 4, RESERVE 5, INVAL 6, SIZE 7, CANCEL 8, NOMEM 9, NOSUPPORT 10, NODEVICE 11, UNINSTALLED 12, NOACK 13而 I2C HIL 正是「自定义错误类型」的典型代表kernel/src/hil/i2c.rs 定义了pub enum ErrorAddressNak、DataNak、ArbitrationLost、Overrun、NotSupported、Busy并通过impl FromError for ErrorCodekernel/src/hil/i2c.rs将自定义错误映射回标准错误码例如地址/数据 NAK 映射为NOACK、仲裁丢失映射为RESERVE、接收溢出映射为SIZE。这套「HIL 内部用精确的自定义错误对外统一收敛到 ErrorCode」的设计正是 2021 年会议纪要所确立方向的最终实现。议题一libtock-rs 的 macOS CI 困境Johnathan 汇报了libtock-rsTock 的 Rust 用户态库的 CI 状况其 CI 负责在 macOS 上测试 RISC-V 构建但成功率仅约三分之一经常超时最长约 6 小时而团队中几乎无人使用 Mac难以高效维护。会议讨论了三个备选方案libtock-rs不再官方支持 macOS 构建直到有 Mac 的成员修复 CI由核心团队中使用 macOS 的成员担任 macOS CI 维护者改为在 macOS 上只测试 ARM 构建绕开 RISC-V 工具链在 macOS 上的安装难题Brad 提出Johnathan 采纳并排在第一优先级。会议还厘清了一个关键事实GitHub Actions 对 macOS 构建有组织级并发配额且配额低于其他平台libtock-rs长达 6 小时的超时任务可能占满配额进而挤占 Tock 主仓库的 CI 资源。Pat 提出了折中方案——只在 Bors 合并暂存分支上运行 macOS CI使其仅作为合并前的最终把关环节因为「Linux 构建通过时 macOS 构建失败的概率本就较低」。最终 Johnathan 确定的执行顺序为先尝试 ARM on macOS其次由 Hudson 接手维护最后才考虑放弃 macOS 测试。议题二Tock 2.0 状态更新会议以 tracking issue #2429 为线索逐项过了一遍 2.0 的收尾工作除更新 changelog 和阻止回调交换外重点讨论了以下子议题。BADRVAL用户态对「返回变体不匹配」的兜底Phil 指出系统调用 TRD即 doc/reference/trd104-syscalls.md 对应的 syscalls 规范在用户态引入了BADRVAL用于表示「内核capsule返回的系统调用返回变体与预期不匹配」这一异常情形但当时libtock-c的大部分代码并未处理该情况。Brad 回应作为ReturnCode更新与向StatusCode迁移工作的一部分libtock-c现已实现这一检查因此不应阻塞发布。从内核侧看「系统调用返回变体」由 kernel/src/syscall.rs 的SyscallReturn枚举完整承载包含Failure(ErrorCode)、FailureU32、FailureU64、Success系列以及AllowReadWriteFailure、SubscribeFailure等带载荷的专用变体。该枚举由调度器构造并下传给架构层编码为寄存器值capsule 侧则通过CommandReturn等受限包装类型构造返回值确保只能构造语义合法的变体。用户态据此可校验返回变体是否匹配预期——这正是BADRVAL存在的基础。ReturnCode → StatusCode错误码跨边界的统一编码ReturnCode到StatusCode的迁移是 2.0 的重要清理工作。StatusCode并非实际的 Rust 类型而是一种「伪类型」它用单个usize表示成功或失败跨越内核与用户态的 syscall 接口传递。其关键设计在于错误码数值映射与ErrorCode完全一致同时用0表示成功——因为ErrorCode按约定不使用0kernel/src/errorcode.rs 的into_statuscode函数正是这一约定的直接实现pub fn into_statuscode(r: Result(), ErrorCode) - usize { match r { Ok(()) 0, Err(e) e as usize, } }kernel crate 导出重组先列清单再动手改Brad 提出重组 kernel crate 的导出由于内核 crate 长期「有机生长」导致使用体验不一——有时需要导入很长的路径有时又可以从 crate 根直接导入有的导入命名清晰有的则不然对应 PR #2545。Phil 建议一种更稳健的推进方式先完整列出目标导出清单再据此修改确保最终结果一致、方向明确。Leon 赞同该方案优于大量迭代式修改。Brad 补充说可以先用一个不含代码改动的草稿 PR 来对齐清单再落地实现。从当前仓库回看kernel crate 的可见性策略已在 kernel/src/lib.rs 的模块级文档中被系统化地阐述核心内核类型仅暴露最小必要接口如ProcessBuffer构造函数被限制为pub(crate)敏感但必须公开的接口如启动主调度循环的入口要求调用方持有Capability服务于内核外部扩展的接口则追加_external命名后缀。这套规则的成型与本次会议确立的「清单先行」思路一脉相承。AppSlice 别名不安全延期至下周三重点讨论Leon 提出一个内存安全问题内核中不能存在两个指向同一内存区域的可变借用切片AppSlice否则属于未定义行为。Amit当天缺席此前给出过 volatile slice 的方向但 Leon 调研后未找到既良好又非侵入式的实现方案其余备选方案也不乐观。会议决议将该议题移至下周例会并赋予高优先级Leon 邀请有时间的成员共同参与——Hudson 主动提出会前与 Leon 沟通并先行调研。议题三阻止 Upcall 交换——全部非虚拟化 capsule 迁移到 Grant这是本次会议最核心的技术议题对应 PR #2462。所谓「Upcall 交换」指进程通过subscribe注册到 capsule 的回调upcall可能被意外替换或错配的安全隐患。Hudson 总结引入「阻止 capsule 交换 upcall」机制所需的工作几乎只剩下把所有非虚拟化 capsule 改为使用 Grant。Leon、Brad 与 Hudson 已分工推进PR 描述中维护着待迁移驱动的认领清单Phil 也鼓励大家各认领一个驱动——迁移过程本身也是理解「非虚拟化 capsule 在新机制下如何工作」的最佳途径。Leon 还指出 PR #2521 提供了一个现成的迁移模板可套用到其余 capsule 上。单进程预留command / allow / subscribe 的策略分歧Hudson 提出了一个具体的策略问题早期迁移的 capsule 只在command系统调用上强制「单进程预留reservation」——若某进程对已被另一进程预留的 capsule 发起command会收到错误返回但allow与subscribe却仍然成功。在他最新的 PR 中这一限制被扩展到全部三类系统调用应用若在command之前先通过allow或subscribe使用驱动其 Grant 区域同样会被分配。代价是文件内容略有增加、代码体积小幅上升。Brad 的观点是非虚拟化驱动本就不特别有用更多用于测试团队更应关注内核的安全性与健全性soundness因此该策略差异不是问题——Grant 区域被分配但驱动不可用的情形可以接受。Leon 则补充了一个语义层面的考量若进程已共享了某些资源而另一进程「抢占」了 capsule 预留权并考虑未来可能释放预留前者将永远无法取回资源从语义上讲「capsule 持有进程状态但拒绝某项操作」是合理的。最终 Hudson 同意按此调整 PR。从源码看 Grant 如何承载 upcall 防交换机制会议所讨论的机制在今日内核中已完全成型。Grant 的类型签名直接体现了「每个进程独立存储」的设计kernel/src/grant.rs 中GrantT, Upcalls, AllowROs, AllowRWs同时管理进程数据、upcall 槽位与只读/读写 allow 槽位并记录driver_num以唯一标识 upcall 归属。upcall 的身份由 kernel/src/upcall.rs 的UpcallId唯一确定——driver_numsubscribe_num的组合使得一个 upcall 只能对应到其注册时所属的驱动与订阅号capsule 无法跨进程或跨槽位交换 upcall。capsule 调度回调时通过GrantKernelData::schedule_upcallkernel/src/grant.rs进行先按subscribe_num在 grant 存储的 upcall 切片中查找越界返回UpcallError::InvalidSubscribeNum再构造Upcall对象入队。而Upcall内部保存的fn_ptr若为 null 则不实际调度kernel/src/upcall.rs对应文档中提到的「null upcall」语义。核心要点是upcall 的存储与读取都发生在进程自己的 Grant 内存区域中而非 capsule 的全局状态里——这就从数据布局层面杜绝了「胶囊交换 upcall」的可能性与会议纪要中「阻止 capsule 交换 upcall 的最后一步是把所有非虚拟化 capsule 迁移到 Grant」的结论完全吻合。会议决议的落地与后续影响本次会议虽然没有产生新的代码提交但确立了一系列影响深远的决策议题会议决议当前仓库中的落地形态HIL 错误码回调 SHOULD 返回ErrorCode类型须一致kernel/src/errorcode.rs 标准错误码 kernel/src/hil/i2c.rs 自定义错误映射syscall 返回值BADRVAL不阻塞发布libtock-c已支持kernel/src/syscall.rs 的SyscallReturn变体体系kernel 导出先列导出清单再修改kernel/src/lib.rs 的可见性与 Capability 策略upcall 防交换非虚拟化 capsule 全部迁移 Grant预留覆盖 command/allow/subscribekernel/src/grant.rs 与 kernel/src/upcall.rs从会议纪要到今日源码KERNEL_MAJOR_VERSION 2kernel/src/lib.rs标志着 2.0 已正式落地。回顾这场发布前夜的讨论可以看到 Tock 团队在系统设计上的鲜明方法论用 TRD 规范约束接口语义ErrorCode 的统一与 SHOULD 措辞、用类型系统与数据布局消除安全隐患Grant 承载 upcall、用「清单先行」的方式推进大规模重构kernel 导出重组。对于希望深入 Tock 内核源码的读者建议沿着 kernel/src/grant.rs、kernel/src/upcall.rs 与 kernel/src/errorcode.rs 三个文件继续阅读它们正是本次会议三个核心议题的最终代码形态完整的例会纪要系列则收录于 doc/wg/core/notes/ 目录。赞分享操作系统嵌入式嵌入式OS【免费下载链接】tockA secure embedded operating system for microcontrollers项目地址https://gitcode.com/gh_mirrors/to/tock点击查看免费下载相关推荐Tock 2.0 内核内存安全设计回顾从 core-notes-2021-04-16 看 Grant 区域、AppSlice 与 Upcall 的演进Tock 2.0 内核内存安全设计回顾从 core notes 2021 04 16 看 Grant 区域、AppSlice 与 Upcall 的演进 Toc操作系统嵌入式嵌入式OSTock 2021-07-02 核心会议解读upcall 交换内核化设计、allocate_grant 机制与代码体积优化Tock 2021 07 02 核心会议解读upcall 交换内核化设计、allocate_grant 机制与代码体积优化 导读 本文深度解读 Tock 嵌入操作系统嵌入式嵌入式OSTock 内核设计解读ProcessBuffer 裸指针化改造、无 panic 访问与错误码体系演进Core Notes 2022-04-22Tock 内核设计解读ProcessBuffer 裸指针化改造、无 panic 访问与错误码体系演进Core Notes 2022 04 22 本篇技术指操作系统嵌入式嵌入式OS创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询