![]() |
|
教学公告
我的国赛OS比赛经验分享:从选题到决赛
----------
一、选题
我认为一个科班出身的程序员,最重要的能力就是 “知道自己不知道”,换言之就是能够清晰地评价的自己的技术储备和代码水平。在选题前,需要根据自己以及队友的能力选择一条合适的赛道。
内核赛道的优势是参赛队伍较少,但对应的难度较高,且赛题难度是逐年递增的(25届的初赛已经出现了24届的决赛赛题)。内核赛道的基本比赛形式是选择一个 base OS,在这个基础上逐渐添加功能,通过赛题给出的测例即可。这个过程不是一蹴而就的,而是需要选择并学习一个合适的OS项目,充分理解项目之后再进行工作。
一开始,我选择的是内核赛道,我以 rcore-os
的 risc-v
版本为基础开始了大约3个月左右的学习。但是在4月份左右我意识到,以我当前的进度和人手储备可能不足以完成内核赛道的开发任务。幸好我及时和李老师沟通,最终决定换成了 功能赛道。
但学习 rcore-os
的过程并没有白费,我在这个过程中完整学习了 Rust
语言如何进行系统级开发,包括 no-std
的配置,一些基础的宏(比如 println
)的手工实现乃至 bootloader
的原理,这为我后续在功能赛道的开发节省了大量时间。
与内核赛道的统一标准不同,功能赛道由各种各样的单一赛题组成,选手只需要选择一个赛题完成即可,其中也包括像“xv6教学课程”这种技术含量较低的赛题。因此参与人数比内核赛道更多,25届初赛有400多支队伍报名功能赛道。
虽然功能赛道赛题多样,但我还是希望能找到内核相关的赛题。也巧,proj-278
就是一个对我胃口的题目:开发一个基于 x86-64 架构的 Rust 内核。结合我的技术储备,我在联系了赛题老师(这点很重要,一定要先联系老师确定标准)后选择了这个赛题。
----------
二、开发
我选择了 blog_os
为基础进行开发,这是一个非常经典的OS内核项目,同样是基于 x86-64 架构。这个项目其实已经实现了很多赛题278的要求:内存管理、中断处理等等,但整体过于简单了,而且很多技术已经过时:比如VGA显示以及PIC8259实现外部中断。
在初赛阶段,我的工作主要是:
-
实现了以 PIC8259 为基础的鼠标中断。
-
修改了内存管理的部分,增加了一个 池化分配 的策略:在内核初始化时,提取分配一部分物理内存到一个内存池,分配时直接从池子取而无需调用内存分配。
-
增加任务模块,基于定时器中断实现一个简单的 时间片轮转调度 的任务模块。
-
将VGA文字模式升级为 VGA图形模式,重构
print
和println
等输出宏。 -
在第4点的基础上,实现了一个 简单的图形界面,包括一系列图形绘制函数、窗口管理器以及事件管理器,通过事件循环模型不断捕获鼠标、键盘中断触发的对应事件做出行为。
我的项目叫 Rix-os
,起这个名字一是致敬我第三喜欢的 Linux 发行版 NixOs
,二是简短好记。新生的 Rix-os
非常简陋,一堆过时的 crate,没有文件系统,系统调用只实现了基本的 sys_exit
之类的,甚至有1/3左右的代码来自别人。但幸好它帮我通过了初赛,总分36分取得了31分的成绩。
进入决赛后,我开始思考 “能让我的项目和其他队伍的项目区分开的东西是什么?”
最终我把重点放在了 图形界面的优化 上,出于以下考虑:
-
相较于其他模块,图形界面的优化更容易 直观对比 出来(主要是VGA图形模式只有324*200的显示率,过于模糊了)。
-
中断、内存这些模块,一直都是OS方向的主题,功能赛道甚至有不少专门针对这方面的赛题,如果重点更新这里,可能会失去赛题本身的优势。
因此,我选择了以更新图形界面为主。更新图形界面是个牵一发而动全身的工程,我的具体升级路线大概是:
更新 bootloader,升级为用 UEFI 引导启动磁盘镜像 → 更新内存管理等模块,使用新的 bootloader_api
→ 更新输出方式,使用线性帧缓冲来作为输出。
顺便把中断系统也更新为现代化的 APIC 实现,抛弃了老旧的 8259pic 芯片。
----------
一些感想与祝福
复盘进入决赛后的开发,其实我个人认为主要是开发时间不太够,这点必须承认。因为决赛前的开发主要是在7-8月份,由于要准备考研,其实留给开发的时间并不多。
当然也和我本人的心态有关,因为我其实并没有对决赛拿成绩抱有特别大的期望,只要能够去决赛的现场就已经让我非常满足,后面拿到奖项属于是意外之喜。
所以希望大家能够想清楚 这个比赛对自己意味着什么?需要付出多少来对待? 这是我认为需要好好考虑的。
夏天是努力的季节,希望大家在人生的每一个夏天都能做出对得起自己、对得起人生的决定,祝好!