予焦啦!一梦终须醒......

佳作之後

承蒙评审给予肯定,最直接的感谢方式就是狗尾续貂一番。

沈淀了一个多月,我时常咀嚼结语中故作轻松的豪语:

所以,就先抓 2025 Q4 释出 Hoddarla 1.0 版吧!

铁人赛毕、回归日常之後,就像松开安全锁之後走下大怒神或云霄飞车座椅的感觉:方才的经历在每一个瞬间都带来极深刻的感官体验,但又已经过去;日後是否能鼓起勇气重新再挑战,也没有足够把握。但,刺激的游园设施经验所能类比的部份,也就只到这里了。

先前最後的规划,2025 Q4?几乎像时间的尽头。但若时间真正到达了尽头,又哪需要什麽作业系统、哪需要什麽典范、概念、工程原则、破坏或创新或沿袭?有太多矛盾本身隐式地存在在这个专案的宣言里面。

要完成 side project,人们必须能从最原始的本能之中提取足够的能量作为核心动力,而後才能够启动:设定目标与阶段、一步步完成、回顾、改善、再前进。然而若这份能量突然空乏(也许是需挪作他途、也许是资源耗竭?),那无论进行到哪里,都不会有达成目标的可能了。

Hoddarla 於我,是过去两年的生命本身;然而类似向度的思考(大部分已总结在予焦啦!结论与展望(一):Hoddarla 专案的过去、现在与未来一文之中),却已经持续了很久,也非我所独有。

但如果我只是继续沉吟,这末篇将会连狗尾的等级也没有;所以,另外引了 2 则来源,希望能够与读者诸君一同品味我将 Hoddarla 1.0 这个目标搁置的决定。也许酐醉到了深处的 underflow,是恰到好处的醒觉也说不定。

是时候让作业系统重新认识它底下的硬体了

这场演讲来自相当开放的系统架构论坛 USENIX 今年(2021)的技术年会(连动 OSDI 研讨会)的 Key Note 讲座。精彩的 Key Note 所需富含的领域深度与洞见,这场讲座当然不缺;而论启发性与娱乐性,更是这场讲座为人津津乐道之处(这一两个月,只要是 Hacker News 上稍微深入的作业系统主题,都会看到人们以这场讲座为参照延伸讨论)。

讲者 Timothy Roscoe 是一位带领 ETH Zurich 系统部门的业界先进。他一开场,就以鸡蛋高墙式的高反差手法指出,OSDI 这个作业系统领域里面影响力最高的一份刊物之中,作业系统本身的学术论文仅是少数;而且在这些论文之中,除了以 Linux 为实验平台之外的作业系统研究,已经稀缺到一年只有一两篇的程度了。

於是下一个问题,思考过作业系统与相关哲学的人决不会陌生,那就是,**作业系统到底是什麽?**又,**为什麽是 Linux?**讲者给出一个很强的断言,我们若是只看到 Linux 在作业系统研究领域的高占比,那就是见树不见林;实际上,就算是 Linux 之外的那些作业系统设计与研究,也与 Linux 共享一项硬体假设: ccNUMA 架构,也就是对各个 CPU 丛集来说,记忆体存取有远近亲疏之别,但同时他们互相之间的 cache 是一致的(coherent)。於是,就此破题。

讲者列举了一些显然一点都不 ccNUMA 的系统方块图,几乎可以说,Linux 以及其他为 ccNUMA 架构而生的作业系统,实际上只是控制真实硬体的 CPU 与部分记忆体而已。真实的其他硬体元件因此需要自己处理这种被解离的情境,它们不过是作业系统透过 driver 去稍微接触的边疆民;有趣的是,这也催生的其他领域的一些研究机会,如安全领域的 cross-SoC 研究、或是各种计算机架构的研究(对他们来说,直接改架构比理解如何调整软件层的东西简单多了),因为那些领域的研究者没有时间使用 Linux 之外的作业系统,所以势必得让周边硬体元件去配合 Linux 存在的状态。

讲者也顺便抱怨了一下 USENIX/OSDI 研讨会,因为里面大部分是机器学习、资料库领域的研究,作业系统领域研究反而少不打紧,其它子领域都有专属的高品质研讨会,就只有作业系统没有;不仅如此,如果硬是要研究作业系统的话,最好都选择在 Linux 上进行;如果不是,也务必让实验 OS 尽量像 Linux(也就是运行在 ccNUMA 假设之下的意思)。

31 分钟,也就是这场讲座的中间点,讲者做了最重的批判:现状(作业系统设计之研究)为何如此远离真实硬体?

  1. 人们根本就不知道现代硬体长什麽样子:这是无知。
  2. 人们停留在舒适圈里面,专注於那些 Linux 本来就擅长的部分:这是否认现状。

作者之後语气放缓,并开始提出一些建议的下一步作法,包含:

  1. 写系统以控制真实的 SoC。确实其中包含许多复杂的部分,但处理复杂、撰写系统以降伏这些复杂度本来就是我们的天职。过程中讲者也提出一篇他作为共同作者的论文:Mind the Gap: Reconnecting Architecture and OS Research,从 2011 年至今也没什麽改变。以结果来说,以 Linux 为大宗的作业系统就这样被排挤,孤立在仅仅占据 CPU/Memory 的一小块角落里面,且有越来越多作业系统看不见的东西(延伸资料:Intel CPU 附赠的 Minix 作业系统),进而导致整体性的问题。
  2. 打造自己的电脑(计算机)吧!讲者俨然是个系统软件禅师,大声诘问:你们理解现在的电脑硬体吗?你们根本不懂!至少从 2011 那篇论文之後,现在要自己制定规格以打造工业级电脑简单多了。讲者自己就简单秀了一下规格与照片,然後描述一般作业系统研究者比较少关注的部分:BMC,也就是主机板上的基本控制器,它负责温度与电量之类的、贴近原生硬体且的关键控制。回头审视 ccNUMA 的假设的局限性,讲者认为安全领域与计算机架构领域的研究者关心的问题其实都非常关键,所以作业系统领域这边也应该跟上才对。

结论也就理所当然了。硬体这些年来的变化非常巨大;工程界很多公司也关注到这个现象而开发了新的作业系统;其它子领域(反覆强调的两个大宗:安全与架构)的关注项目需要作业系统研究者跟上。然而,这个社群(USENIX/OSDI)并不鼓励类似的研究,大环境否认了有在 Linux 之外的其他大问题,并且对於真实硬体的样貌呈现给软件的现状缺乏认知。不过也因此对於作业系统研究是崭新的机会!

  • 真的应该要为新的硬体们构思新的作业系统架构
  • 现在的工具远比以前好多了:新的正规方法、语言、新的硬体...

Hoddarla?

在赛期中接触到这个讲座带来莫大的鼓舞。从结论就可以看到,讲者鼓励新的语言和新的概念,然而遗憾的是,笔者至今接触过的 RISC-V 机器,要不是相当简单的平台,再不然就是模拟器,并没有真正进行新机器的探索。

但是,讲者在有头有脸的研究单位里面,又为居高职,他可以支配的资源量,才是支撑他作出这些乎告背後的靠山;现状之所以如此,必有诸多原因,演化至今使然

至於未来,我认为若要待在能够盈利的主流当中,还是只有 Linux 可以考虑;非 Linux 已经是离经叛道,遑论是非 POSIX 甚至排除 C 语言。所以认真说这个部分的未来事项的话,我将会开始研究最近成形的 RISC-V 进阶中断架构(Advanced Interrupt Architecture),这个新机制应该在两三年後会普及并取代现今的 PLIC 做法,或许在许多硬体本身的控制器也转为 RISC-V 的情况下,更有望支援类似於讲者期望的那种作业系统也不一定。

21 世纪了,作业系统架构呢?

相较於前篇讲座佳评连连,这系列文(共四篇)的评论却是稍微的负面,其中甚至也有评论说,作者点出一大堆他自己都没有深入了解的问题。为此,我本身也是没有了解任何主题到足以称之为深入的人,所以就在旁边看看热闹。也许众人的评论自有道理,作者非常稀疏地更新,从 2020 二月之後就没有後续了,将系列文停留在架构构想阶段。

这个部落格中,作者只有部落格用的艺名 "No Bugs" Hare,行文是我行我素的美式口语幽默,完全不怕争议处采他人痛点,与前一篇的讲者在争议处会放缓打预防针的做法完全不同。敢放话 No Bugs,对於技术当然是有一番见识的。

第一篇描述过去五十年的硬体与软件生态系进展,为之後的论述打地基。硬体部分的改进或差异至少有以下数点:

  1. 效能,无需多说
  2. 不同元件的效能改进不同,CPU/Memory 之间处理资料的速度越差越大
  3. context switch 变得相当昂贵
  4. NUMA
  5. Interrupt 的改进
  6. 更深的 pipeline,分支预测等软件看不到的 CPU 改良

软件部分,大多与工具的功能增强有关:

  1. 静态分析工具
  2. 公共签署的实务:增加使用者对软件的来源的信心
  3. 应用程序层有更好的「不分享任何东西(Shared-Nothing)、讯息传递(Message-Passing)」式的 API 在不同的语言框架中供使用。作者也引述了 Golang 的 Channel 设计背後的核心精神:Do not communicate by sharing memory; instead, share memory by communicating。
  4. 非同步的程序设计框架。

第二篇则是列举作者希望能够在现代作业系统中改良的八大项目:

  1. 增加弹性:以布署时的控制选项,取代现在主要是开发时或编译时的控制选项。
  2. 无论是低阶的 MCU 或是高阶 CPU,藉由一样的作业系统介面,使得双方可以共享应用程序与驱动程序,而非各自开发各自的。
  3. 增加稳定度与可测试性,尤其是正式上线的生产环境的除错经验应有所提升。一例是,很多生产环境 crash 掉的问题根本很难解决,如果能够有个监控机制,让人们可以调度事发前一段时间的系统状态,那显然会更好。以我的认知,这当然现在很多工具能够提供,但这里是问,为何不能是作业系统提供的呢?
  4. 内建容错(Fault-tolerance)以及扩容(Scalibility)
  5. (需要安全性的情境)增加安全性。
  6. 解决公共财的悲剧(参见维基),作者应是意指多租户或多使用者情境下的系统利用状态。
  7. 驱动程序开发应当被简化
  8. 增加效能,且须分开考虑 HPC(高效能运算,通常 CPU 负责绝大部分任务)与互动式工作。

我认为作者遭受到的批评多是,这些作者希望可以改进的面向,都有一些相对应的措施或工具,是作者没有评估过的。这些批评本身有其道理,但显然作者不仅仅是希望那些改进的做法存在,实际上他更希望的应该是在作业系统核心与应用程序之间重新设定边界,否则无异於多出一个又一个的框架或是第三方函式库。这些也有可能只是我自己内心想望的投射,但总之我是这麽解读的。

第三篇比之前篇更进一步,从想要的功能到基本的想法。如果当初这个系列持续下去,那麽这篇应该就是最基本的蓝图。比之前篇描述的每个改良都只是小段落的撰写,本篇提出五个功能且都是较长的段落,我直接做结论的话不免有点破坏性压缩,这里先行致歉;但读者诸君应该可以感受到那份动能:

  1. 原生支援事件驱动(Event-driven)式的程序设计模式,且支援手持装置、桌面系统与服务器。事件驱动模式通常是透过程序语言、框架或是函式库来支援,为了支援这样的方法给应用程序层,其实费了很多工夫;之所以需要费工夫,是因为底层系统本质上是中断驱动(Interrupt-driven)式的。作者认为,如果大部分的事件处理都可以很快解决,那事件驱动模式不是很显然优於中断驱动模式吗?考量到多执行绪的切换与维护在现代作业系统之中是何等的高成本(原文是 heavy-weighted),作者的出发点如此。更到细节处,他认为应该以有限状态机(Finite state machine)作为执行的单元,事实上,很多现代的嵌入式作业系统或是即时作业系统也有类似的设计;作者在这一点上想要主张,就算是给高阶处理器运行的作业系统,也应往这个方向靠拢才对。以网页服务器效能为例,non-blockng 的 nginx 能够优於 apache。
  2. 既然所有东西都是 FSM,那麽系统在执行时的行为就会是可决定(deterministic)的。这有助於检验生产环境上的 crash 事件。理论上,一台机器上记录下来的 log,应该也要能够在其他运行相同系统的机器上重现出来。理想上,这也可以简化迁移(migration)的流程。
  3. 作者企图重定义作业系统:它不应该只指涉核心,而应该指涉相同的 API、可提供相同的应用程序与驱动程序运行、但允许配备不同的核心。我认为这就是原系列作者最会被现实阻拦的一个设计原则。有个例子是网页服务器阅览自己的组态档的需求,在 Unix-like 系统你必须有个 open 系统呼叫来与档案系统互动,也许有某个应用程序层的 API read_conf 使用到 open,可是如果这个服务器想要运行在没有档案系统的微小系统上,这个 read_conf 就不堪使用了:为何不是定一个作业系统 API read_conf?
  4. API 应该要分群,并且让应用程序的设计者决定它需要用到哪些,於是就只使用那些就足够。我的看法是,这点直接延伸第三点,完全从应用程序设计者的角度出发,并提出兼具「应用程序仅使用需要的 API」以及「高层级 API 允许底层作业系统核心的抽换」的解法。延续第三点的网页服务器案例,设计者就可以选择使用 read_conf 与 sql_socket,而非限定 Unix-like kernel 的 open、read 与 socket API。
  5. 这一点我不太能够理解其中的精神旨趣,但作者倡议作业系统与程序语言的编译器应该更紧密合作,以呼应第二篇当中援引现代程序语言的静态分析工具的优势。

第四篇名为第一份草稿,比前篇更接近实际的设计,这里就先跳过吧。

Hoddarla?

我原本以为我是个反社会的恐怖主义者,但与作者 "No Bugs" Hare 相比,我根本是传统价值的乖乖牌;以系列文相比,我单纯以 Golang 这个语言,比照以往的作业系统,照顾贴近硬体的抽象层级,但这个 XXI 系列充满了更多想像。原作者部落格下的留言大多不以为然、转发至 Hacker News 之後众人的评论也不太优;相较之下,Hoddarla 本身没有获得任何回响,甚至不如驱车入巷时突然猛吠的狗那样能够引人一瞥。

真的要说这个系列文给了我什麽除了技术发想之外的点子,我觉得最接近第一时间感受的是这篇文章:你的高明点子毫无价值

这是 Stonemaier 设计师 Jamey 的文章,是指引有志於桌游设计的人们的一系列心法中的一篇。一言以蔽之,**你以为你的点子聪颖无比,但要是没做出东西来,什麽都不是:那些实践的过程与结果,远远比你构想出一个神妙点子困难得多!**呃,当初乍看也是一把无明火,要是没有点子,人们能够作出什麽东西?但事实是,尽管梦想家比例占全人类是少数,但总数实际上也是不少,实践者与协调者总是会有好点子可以做。以结果来说,当然就是没有被实现的梦想与不存在或是烂主意并无二致。

甚至可以更极端的说,搞不好,实现率低的梦想家的价值更低也不一定。换个角度看比较容易理解,创业失败的人受人景仰的程度,应该会远大於一直在讲自己要创业但什麽都没做的人吧。这有点流於功利主义,但梦想的尽头难道不是为这个世界带来什麽更好的改变吗?这不纯然是结果论的,那些过程也是梦想兑现途中的一部分成果,重点是做,现在就做。这大概就是为什麽 Nike 品牌形象这个好的缘故。

本来期待这个系列最後会引导到某个比 Hoddarla 的尴尬小 console 更高明的东西,但看到一个系列停止更新在 First draft,难免惆怅。

永远站在鸡蛋的那一边?

很遗憾,无论如何,高墙是正确的。

日前与同是晶心壮士的队友 Quechuas 聊聊彼此在技术路上的梦想;知晓他的远大梦想(这里就不多泄漏他人秘密)之後,我追问:

「既然如此,你在做铁人赛或是这些其他的事情的时候,不会觉得自己还是太循规蹈矩了吗?」
「毕竟还是有很多要看要学习的事情,对我来说现在就是吸收养分的时候吧。」
「理解...但对我来说这是一个很煎熬的震荡。每当我觉得安排自己走在正轨上,想要好好吸收养分的时候,不由得会觉得自己太乖了;反过来,像这整个 Hoddarla project 做一做,又会一直觉得该学的东西都还学不够。」

梦想、规划、执行一年半、冲刺三五个月、沉淀、佳作、再沉淀、...我应该会选择永远让 Hoddarla 停留在这个 0.1 的状态,几年内应该也不会再做作业系统专案的尝试了。

典范之所以是典范,就是因为它经过岁月风沙淘洗,仍然与人们共存、共生、共演化。人类在这里面并不是唯一的主体或是宰制者,至多是有脑细胞的 player。看看 C 语言,看看 Linux,看看 Linux Foundation(!),这些概念从某些前辈(们)的脑中跃出之後,不只是一本本长灰尘的书,而是以电流为血、以概念为肉的巨大神物。

要挑战神兽?没血没魔没装没天命,有何可战?

作业系统专案的尝试 == 自干作业系统?

我的答案是否。这两件事情应该区分开来看。先说第一件事,这比较接近 Hoddarla 或是 "No Bugs" Dare 想做的事情,这通常会被业界先进们归类为经验还不够的那一群。

我倾向於认同 Timothy 先生在讲座中提到的(以及引用的 2011 年论文)那个角度,你们这些梦想家,想要挑战甚至改动的作业系统原则那麽多,那你们光从软件层做,真的够吗?一样的硬体假设之下,会不会到头来就算给你做起来,也不会和现在差太多?

所以我觉得,反正之後 RISC-V 开源核心只会越来越多。应该把硬体的一些概念重新补回来,也许之後连同硬体层一起改,让软硬之间更能够互补所需,应该会是更有趣的专案。这是从作业系统往下看去的角度。另一个角度是,Hoddarla 本身想要将 Golang 的执行期作为作业系统的一部分,但现在可以很直接地说,结果太丑陋了,没有维护性。至少 Golang 直接套用,没有可行性;若要维持在 Golang 里面,至少要付出像是 TamaGo 专案那样等级的心力才行,再不然就连程序语言也需要另外思考:语法简洁、节省开发者认知资源、工具众多...

另外一件事情,关於自干作业系统,我的认知上,不管是作业系统课堂或深或浅的作业,或是技术狂人们的实作,本质上是使用手边的工具重现实务上使用的作业系统的一小部分。这不是我想要走的路,尽管过程中一定可以学到我现在缺乏的某些技术或知识,但是结果仍然只是玩具,而我不希望我做出来的东西只是玩具。

话虽如此,光是这些骇客们能够好好「自干」并且做得出来的行为本身,就足以让上述第一种人看起来像是逃避仔,关於这个看法我可以大方承认,对,我是想要逃避 C、POSIX、everything is a file、还有企鹅或是红色恶魔。

关於玩具,当然也是有这种说法倡导它的价值,但影响力是一回事,创业营利又是另外一回事。

学习的面向或许是唯一一个创造玩具的好理由。如果直接让学生潜入 Linux 或是任何大系统,并且要求他们在里面找到痛点并修正,是的,听起来需要很久的时间,而且如果学生的经验都是 Input 而没有 Output,效果不可能会好。如果是创造玩具的话,学习的认知上有进有出,可以预期这个方法的效果。

打造玩具学习法有一大原因是它可以节省日後接触真实系统需要的上手时间,而花在了解玩具的复杂度上也不会花太多时间;也就是说,教学者的心智模型是直接深潜至真实系统中所需的时间远远大於打造玩具过程中理解系统基本元件所需要的时间加上有过玩具经验之後上手真实系统的学习时间

可是出了社会之後,我总觉得直接潜入真实世界也未必有什麽坏处。因为大部分人在就学时期连玩具都造不好甚至没造过,工作之後能够自由支配的时间更为稀缺,这时候再做玩具,对我来说毫无意义。

以 Side project 作为铁人赛系列文在夺奖上的劣势

最後聊聊这个劣势。恭喜 Kuma 大大获得 Software Development 组冠军。整个系列文的节奏分配,确实有登楼梯的感觉。除了程序码的实例也通常夹带重构心法,目标读者群大,也易受益。

反观我过去的几次尝试大多非常自我中心。Side project 这种东西本来就只关乎自我成长,虽然 Hoddarla 是企图让 RISC-V 的一些面向透过实际操作的方式展露出来,也比我先前的几次尝试来得完整,但整体上对於学习来讲还是略显虚浮,没有去芜存菁的感觉。

当然,如果是仅仅以参加为目的,那就没有所谓的优势劣势。但是除了兴趣型专案,我也没有什麽独到的领域型专门知识可以整理并以教学为目的分享成系列文的料,所以未来如果会参赛,核心应该也都还是这种形式吧。不求扭转劣势,但是还是可以考虑些策略。如果有争奖打算,下次就回避 Modern Web 和 Software Development 这两个一级战区吧。

给评审与主办单位

如果可以的话,是否能够公布评量的一些向度,与得奖的系列文在那些向度获得的分数或评语?如此一来,不但未获奖的多数技术人能够有个目标,得奖者也相当於是获得了回馈以增进自己传递知识的能力。

由衷感谢!

给读者

希望你不会因为我在这最末篇宣告 Hoddarla 1.0 永远不会出现而感到阅读这个系列是在浪费你的时间。

理论上,大部分的 RISC-V S-mode CSR 我全部都有说明并使用,尽管不是很有系统,但却是在 Hoddarla 这个系统建构的脉络之下有逻辑地进行的,所以至少这个部分可以作为一点学习的参考;事实上,过去一个多月,我自己已经拿出来参考过几次 PLIC。

Golang 的系统面向则是非常偏门,也需要往复搭配我前年的系列才能够比较清楚地阅读。确实这个部分会非常难以入口吧,尤其是系统软件圈多的是只知道 C 而不知道 Golang 的人们。

绝大部分我都采取最生硬且最形式化的方式来表达在文章上面,确实是我刻意为之的结果,因为我一直认为这是表达对於读者的尊重的方法。若实际上的成效相反,那只能说我对这个世界的误会大得让所有人都会遗憾。

最後的结论以及本篇则是宽松之後的结果,更接近我日常行文的方式,读来也许自溺,但我觉得这样很有趣。我推荐读者诸君也试着创作,我们可以在铁人赛或是其他部落格相遇,更重要的是你自己也会在未来与先前写作的自己重新相遇,那种经验几乎堪比接触陌生人:举例来说,我现在看自己先前的三个铁人赛系列,我完全不认得那些笔调,精神与生命同等的随着岁月遗失,留下来的则大部分是那些程序码的概念与能够让我赖以为生的技术。

感谢你们的阅读,如果不是阅读,这些文字与程序码的存在毫无意义。

请接受这过早的佳节祝福,也希望 2022 对所有人来说同样是能够带来机会与成长的一年。


<<:  【前端效能优化】Lighthouse 检测後将图片转为 webp 格式

>>:  2021/12/12 更新

Day14:【TypeScript 学起来】Interfaces(介面) 笔记整理

终於来到 interface,觉得这个算是颇重要的一趴,让我们看下去。这大概是我最认真做笔记的一篇...

Day30:30 - 总结

大家好,我是Charlie! 铁人赛终於到了尾声,在这30天的时间当中,我们完成了一个基本的购物网站...

应用 LINE Front-end Framework 轻松建立互动 (1)

我们的验证码小帮手现在可以完成的项目有: 对使用者进行身份验证与绑定 判断使用者的讯息,进而回覆对应...

Day 26 长短期记忆网路 LSTM

介绍 我们昨天提到,RNN 虽然是一个可以很好处理序列资料的神经网路,它能够将前面所学到的部分资讯一...

Golang 变数与型态

Golang 变数与型态 在开始变数之旅之前,我们需要先了解各型态变数的预设值 直接来上点范例吧!!...