
操作系统嵌入式嵌入式OS【免费下载链接】tockA secure embedded operating system for microcontrollers项目地址https://gitcode.com/gh_mirrors/to/tock点击查看免费下载本篇技术指南以 Tock 核心工作组Core Working Group2024-06-07 会议纪要原文见 doc/wg/core/notes/core-notes-2024-06-07.md为骨架逐项还原会上围绕三项内核级设计议题的讨论、分歧与最终共识面向 ADC 流式传输的缓冲区交换方案PR #4023、yield-wait系统调用的落地推进、以及基于 AppID 的存储权限 TRDPR #4021。读完本文你将理解 Tock 在内核与用户态共享缓冲、进程等待异步事件与持久化存储访问控制三条主线上正在发生的设计演进并能结合当前仓库源码kernel/src/syscall.rs、kernel/src/process_standard.rs、kernel/src/storage_permissions.rs验证这些设计的实现形态。会议背景与参与人员本次例会由 Tock 核心工作组周例会机制召开该工作组负责管理并引导 Tock 的代码、文档、测试与发布其章程见 doc/wg/core/README.md。参会者包括 Alex Radovici、Brad Campbell、Amit Levy、Pat Pannuto、Leon Schuermann、Johnathan Van Why以及被邀请参与 15.4 议题讨论的 Tyler。会议无例行进展更新Updates: None全部时间用于三个议题的技术讨论。议题一Buffer Swapping PR——流式数据的缓冲区交换设计本议题围绕 PR #4023Buffer Swapping展开核心场景是 ADC 等流式/网络数据传输中用户态与内核共享缓冲区的交接问题。问题本质驱动无法感知缓冲区何时被交换Alex 首先阐述了问题背景应用使用两个缓冲区交替使用swap而驱动并不知道应用在何时完成了交换。当内核需要按索引indexing写入数据时如果用一个 command 系统调用去通知交换已发生就会引入竞态条件race condition。Brad 在会议总结中对问题做了精炼概括内核从数据源获取数据当数据到来缓慢时大多数驱动没有问题挑战在于数据快速到达时内核必须始终有一个可以写入数据的缓冲区。为此需要多个始终可用的缓冲区。该方案采用单个 allow 缓冲区内核可在其中放入多个数据项通过 upcall 通知应用有数据了应用随后重新 allow 一个新缓冲区——这一重新 allow 在应用侧是近似原子的操作。方案之争双缓冲交换 vs 环绕式 ring buffer会上存在两种设计路线双缓冲交换swapAlex 提出的方案即维持两个缓冲区并由应用侧交换。环绕式 ring buffer由 Leon/Amit 在上一轮会议中命名Alex 沿用该称呼但明确承认它实际上只是一个缓冲区。Leon 认为 ring buffer 是更通用的设计并指出其内存安全性没有问题因为 Tock 在用户态与内核态之间切换时任意时刻只有一方在运行不存在 mutability/immutability 的 unsoundness。但 Alex 随即提出关键质疑一个在内存中不连续的 ring buffer 如何被应用消费这暴露了环绕式 ring buffer 在切片并取得所有权slice and take ownership上的困难——Leon 补充道若从 15.4 收到一个包再转发给以太网Alex 的方案更容易把数据传递给其他子系统而 ring buffer 在包中途环绕时很难实现。Brad 进一步指出ring buffer 的难点在于包大小不一定已知而在 15.4 中包大小是已知的因此 15.4 的 ring bufferTyler 实现填满时覆盖旧包得以成立但对通用场景实现一个包中途环绕的 ring buffer 很困难。checksum 的作用与信任模型争议Alex 的设计中引入了一个校验机制对缓冲区前三个字节做 XOR用于检查应用是否已把前四个字节置零。其作用是当共享缓冲区未被正确初始化时例如之前被用作其他用途校验失败会让 capsule 重置缓冲区从而避免无法向格式错误的缓冲区写入的窘境。对此存在明显分歧Leon 持保留态度这类检查在其他实现中并没有做内核默认应用只会 allow 未被其他应用使用的内存这不该由内核负责管理。Amit 的视角这并不是不信任应用而是允许应用自己坑自己shoot itself in the foot。他追问若没有 checksum最坏情况是什么答案是 capsule 无法向格式错误的缓冲区写入而有了 checksum内核可以检测出格式错误的缓冲区未置零并主动重置。Alex 本人表态对是否保留 checksum 没有强烈立场。这一争论本质上是对 Tock 内核信任模型的边界讨论内核是否应当为应用提供自我修复能力还是保持最小干预。15.4 的兼容性与新包 vs 旧包权衡Tyler 确认该方案对 15.4 可行目前 15.4 使用两个由应用交换的缓冲区每个缓冲区是一个覆盖最旧数据的 ring buffer大小为 n 个 15.4 包大小切换到 Alex 的方案改动不大。Brad 补充了现状差异ADC 驱动有多个 allow 缓冲区并遍历使用而该 PR 只使用一个 allow 缓冲区但减少了系统调用次数。会议还讨论了数据丢失语义Alex 的方案在数据到来过快时丢失新包从通知应用到应用重新 allow 之间存在窗口而 15.4 的 ring buffer 丢失的是旧包。Leon 强调非定长包non fixed size packets同样重要。关于可变长度包Amit 提出两种思路让包自身携带长度信息或在驱动语义中前置长度字段prepending。会议结论就是否实现 ring buffer 功能进行表决Amit/Brad/Leon 一致投反对票对 Alex 的 ADC 流式场景ring buffer 过度复杂该方案的核心价值在于流式传输streaming。Amit 将这一设计定位为一个网络队列a network queue。Alex 同意将 PR 更名不再使用 ring buffer 命名使其名称更贴合流式缓冲的实际语义。Tyler 将在会后详细复核确认与 15.4 的兼容性初步判断无问题。议题二Yield Wait——让应用可靠等待异步事件第二个议题是yield-wait的推进状态。Brad 列出待办审查现有实现、确认是否需要更新、并做更多测试。Alex 主动承担该项工作Amit 评价其影响面很大、非常重要very high impact and important。需求来源教程暴露出的可靠性问题Leon 说明需求来源该需求在准备教程时出现并产生了大量问题。有了yield-wait将更容易编写可靠的应用Alex 也反馈自己遇到过相关问题。这解释了为何该特性被列为高优先级它直接改善用户态应用编写异步逻辑的体验。源码视角yield-wait 的语义与实现从当前仓库源码可以印证该机制的设计与实现在 kernel/src/syscall.rs 的 yield 系统调用类说明中第 43-51 行当进程调用 yield 时内核检查是否有待处理的 upcall若有则将一个 upcall 压入进程栈若没有yield-wait将使进程睡眠直到某个 upcall 被触发而yield-no-wait则立即返回。kernel/src/syscall.rs 定义了返回类型SyscallReturn::YieldWaitFor(usize, usize, usize)携带三个返回值参数。kernel/src/kernel.rs 在 syscall 分发处通过.set_syscall_return_value(SyscallReturn::YieldWaitFor(a0, a1, a2))设置返回值。kernel/src/utilities/arch_helpers.rs 中将YieldWaitFor与 TRD104 系统调用返回值规范互相转换TRD104SyscallReturn::YieldWaitFor涵盖 32 位与 RISC-V 64 位两种编码。进程侧的关键实现在 kernel/src/process_standard.rs新增进程状态State::YieldedFor(_)等待特定 upcall 的 yield 状态并配套字段is_yield_wait_for_ready: Cellbool第 571 行记录该进程在YieldedFor状态下是否有任务就绪。enqueue_task第 598-647 行在入队任务时若发现进程正等待该 upcallState::YieldedFor(yielded_upcall_id)与入队任务的 upcall id 匹配则设置is_yield_wait_for_ready为 true。代码注释特别说明若进程等待的是另一个 upcall不清除该标志以免重新引入 issue #5195 的竞态条件。ready()第 649-656 行判断进程是否可调度State::Running恒为就绪State::YieldedFor(_)取决于就绪标志普通State::Yielded则看任务环缓冲区是否有元素。由此可见yield-wait的落地方案不仅包含睡眠直到 upcall 到来的基本语义还针对等待指定 upcall的场景做了精细的状态跟踪与竞态规避这正是会议上让可靠应用更易编写诉求的实现基础。议题三Storage Permission TRD——基于 AppID 的存储权限架构第三个议题讨论 PR #4021Storage Permission TRD其设计文档即 doc/reference/trd-storage-permissions.md。演进脉络从 TBF header 到 AppIDBrad 说明现有实现源于 TBFTock Binary Formatheader 中的存储权限字段TRD 与之非常相似但有小改动。关键差异在于使用 AppID 标识任何存储内容的属主——旧有的 storage permissions header 未使用 AppID因为当时 AppID 尚不存在。因此该 TRD 实际上是让存储权限架构与既有威胁模型四年前已稳定保持一致正如 Johnathan 所指出的这个 TRD 只是让存储 TRD 符合我们已经稳定的威胁模型。TRD 的定位默认策略还是强制策略Amit 提出两个关键问题该 TRD 是否规定了未指定情况下的默认策略是否意味着不允许存在采用不同策略的存储驱动Brad 的回答划定了边界策略如何设定是另一回事不同驱动的不同实现可以采用不同策略设计意图是只要没有东西使应用丧失访问自身状态的资格应用就应当能访问自身状态该设计让需要被明确排除这一点更加清晰若某实现要存储状态它必须提供获取应用权限的 API必须使用内核的权限系统并且必须用 AppID 标识附着于应用的状态使用不同的权限系统将需要 fork Tock。Leon 追问该 TRD 与未来更丰富抽象如文件系统的关系。Johnathan 给出 Unix 类比在 Unix 中与之对应的抽象是user而这里 AppID 扮演了 user 的角色。Amit 设想可以将权限实现附着于每个存储系统对象上。讨论最终达成补充意见可在 TRD 中加一句澄清——本 TRD 描述的是 canonical规范情形不限制其他使用场景与未来实现。Alex 则预告计划在夏季实现 FAT 文件系统。源码视角权限模型的五种形态当前仓库的 kernel/src/storage_permissions.rs 已实现该 TRD 描述的权限架构。核心类型StoragePermissions内部为私有枚举StoragePermissionsPrivate包含五种权限形态第 33-63 行变体语义SelfOnly(NonZeroU32)应用只能访问自己的状态写入即写入自身 ShortId 标识的状态NonZeroU32即应用的ShortId::FixedFixedSize(FixedSizePermissions)可配置是否可写、是否可读写自身状态并支持最多 8 个可读标识 8 个可修改标识每个为 u32Listed(ListedPermissions)同上但读写标识来自静态切片static [u32]数量任意Kernel仅供内核使用允许内核存取标识为 0 的状态但不授予内核访问应用状态的权限Null应用对任何持久化状态无访问权限构造方法均受 capability 限制如ApplicationStorageCapability、KerneluserStorageCapability确保权限只能通过受控路径创建。对外暴露的判定 API 与 TRD 一致check_read_permission(self, stored_id: u32) - bool查询是否可读某存储标识check_modify_permission(self, stored_id: u32) - bool查询是否可修改某存储标识get_write_id(self) - Optionu32取回写入时应使用的存储标识无写权限时返回None。对应 TRD 的设计要点见 doc/reference/trd-storage-permissions.md应用写入数据时必须以其 ShortId 作为存储标识权限分三种独立类型——write 是布尔权限要么能写要么不能写read 与 modify 是(权限类型, 存储状态标识)的元组仅与特定存储标识关联。例如一个应用可以拥有读取特定数据的权限却没有写入新数据的权限三种权限彼此独立可组合。权限检查的判定逻辑以check_read_permission为例kernel/src/storage_permissions.rs各变体的判定规则为SelfOnly(id)仅当stored_id id时允许FixedSize(p)/Listed(p)若read_modify_self为真且stored_id等于应用自身 AppID 则允许或stored_id ! 0且出现在 read 列表中则允许FixedSize只扫描前read_count个有效条目Kernel仅允许stored_id 0Null恒为false。这套逻辑清晰体现了应用默认可访问自身状态、跨应用访问必须显式授权的设计意图与会议上 Brad 所述除非被明确排除否则可访问的方针完全对应。会议共识与后续动作综观本次会议三项议题均取得明确结论流式缓冲PR #4023放弃 ring buffer 路线保留单 allow 缓冲区 upcall 通知 原子重新 allow 的简洁设计PR 更名以反映流式语义Tyler 会后复核 15.4 兼容性。yield-wait由 Alex 负责推进待办为审查实现、必要更新与扩充测试目标是提升应用异步编程的可靠性。存储权限 TRDPR #4021确认以 AppIDUnix 中 user 的对应物作为存储属主标识权限系统由内核统一提供不同驱动可有不同策略但必须走内核权限 API考虑补充canonical case澄清句并预留文件系统等未来抽象的空间。这些讨论与当前仓库中 kernel/src/syscall.rs、kernel/src/process_standard.rs、kernel/src/storage_permissions.rs 的实现相互印证会议纪要是设计决策的现场记录而源码则是决策落地后的最终形态两者结合阅读可以完整还原 Tock 内核在流式 I/O、异步等待与存储安全三条主线上的演进逻辑。赞分享操作系统嵌入式嵌入式OS【免费下载链接】tockA secure embedded operating system for microcontrollers项目地址https://gitcode.com/gh_mirrors/to/tock点击查看免费下载相关推荐Tock 2024-12-06 核心工作组会议纪要解读隔离存储、寄存器类型抽象与硬件 CI 驱动的发布流程Tock 2024 12 06 核心工作组会议纪要解读隔离存储、寄存器类型抽象与硬件 CI 驱动的发布流程 本文是对 Tock 核心工作组Core WG2操作系统嵌入式嵌入式OSTock 网络栈演进纪事从 802.15.4 缓冲区安全到 PacketBuffer 上流化Network WG 2024-07-15Tock 网络栈演进纪事从 802.15.4 缓冲区安全到 PacketBuffer 上流化Network WG 2024 07 15 导读 本文依据操作系统嵌入式嵌入式OS2024-06-15 贡献者会议纪要2024 06 15 贡献者会议纪要 决策事项 x 采用方案B实现泛型数组解析 1234 行动项 username: 7月1日前提交方案B的实现PR use开发工具代码生成文档上一篇Newton与Blender集成3D建模与物理仿真的工作流下一篇终极指南如何使用Pipenv实现无缝团队协作与完美版本控制创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考