前言
我不是很喜欢Rust。可能是因为使用它的人太张扬了。所以我打算学习生态更小更变态的Zig,算是一种恶心Rust传教徒的办法罢(笑)。
因此,我打算以Zig为核心语言来编写一个RTOS,权当练手的同时体验一下Zig的风味。至于这个标题,其实是neta了一本书《禅与摩托车维修技术》,因为我做的系统取名是
RedChamber,也就是红楼,在龙脉常歌里面是一艘飞船。
Zig helloworld
任务调度
假设我们有一系列原子的任务不能再拆分了,然后作为RTOS的任务/线程去执行。那么,显然会有很多上下文切换负担。但是如果我们随意组合这些任务,又会产生一些问题:不同任务的优先级不一样,有的需要在严格时间内完成,有的只需要在某个时间段完成即可。因此,如何处理原子任务之间的依赖关系,以及优先级,尽可能合并任务,就是操作系统使用者和开发者所需要考虑的一大问题。
总的来说,这个思路颇类似计组中的微指令,有三条原则:
- Deadline不能小于总耗时 合并的原子任务里,最紧的 deadline 是 D_min = min(Dᵢ)。合并体的 deadline 不能比这个更松,否则那个最急的任务被拖死。
- 合并后整体仍然可调度
- 相位对齐 原子任务 a 原本在时刻 t 到达、t+ε 就能跑;合并后它要等合并体的下一个释放点,最坏多等 T’ - ε。这个额外的响应延迟(release jitter)要加进其他依赖它的任务的 RTA 里。如果某个外部任务的 RTA 本来就紧(R ≈ D),加一点 jitter 就爆——这时候合并省下的那点切换开销抵不上 jitter 引入的不可调度性。
其实本质上,这是把零散任务整合起来批处理的一个过程。在Zephyr中,tickless就用了类似的思想,它先估计睡眠时期需要完成的任务,通过尽可能在醒的时期一次性完成大量工作,同时避免影响任务本身要求的时序。
这个思想有一个名字:task allocation / task fusion for schedulability。除了Zephyr以外,AUTOSAR OS 的 ScheduleTable、Linux 的 timer coalescing也用了类似的设计。