Skip to content

宏内核化探讨

Starry的工作是为一个面向Unikernel设计的OS添加宏内核支持,因此相比于其他从0开始的 内核,Starry需要考虑更多兼容工作,也要求我们对Unikernel和ArceOS有足够的了解。

前期知识了解

首先,我们了解到ArceOS是以Unikernel架构运行的。因此我们查阅了Unikernel和宏内核相关的资料,并且总结出两者之间的一些简单的区别如下:

avatar

另外,我们也详细阅读了ArceOS的代码,总结出从ArceOS到宏内核需要完善的内容:

avatar

通过阅读ArceOS与其他宏内核如zCore、rCore的代码实现,将ArceOS与宏内核的关系划分如下:

  • ArceOS中可直接沿用:log、driver以及一系列解耦的crate
  • ArceOS中需要调整适配:任务调度、特权级转化等
  • ArceOS中需要添加:地址空间、进程、信号、文件系统、用户库等内容

开发内容

依据前期知识的总结,我们在原有ArceOS的基础上做出了如下改动:

avatar

在原有ArceOS代码的基础上

  • 新增了4个模块:分别为
  • axmem:添加多地址空间
  • axprocess:添加进程管理
  • axsignal:添加信号模块
  • axfs:添加适用于宏内核的文件系统接口
  • 改动适配了5个模块:分别为
  • axhal:主要为关于宏内核的trap处理,如syscall、缺页异常等
  • axtask:主要为task信息的补充,如计时器信息
  • axdriver:主要为ramdisk的补充,为比赛加载测例服务
  • axruntime:主要为内核初始化流程中添加宏内核启动相关服务
  • axnet:主要为Linux相关的syscall添加相对应的接口
  • 新增了一个用户库:封装Linux相关的系统调用,处理相应的syscall
  • 共涉及代码约12000行

开发重点

进程实现

为了保证Starry可以较好地去适配Unikernel架构,在比赛初期我们就进程结构与线程是否分离这个问题进行了讨论。

在Linux中,进程和线程合并在一起,统一由pthread控制块进行管理,某种程度上简化了结构。但我们的Starry需要适配Unikernel,在Unikernel中是单应用程序,没有多进程的概念。因此作为兼容Linux应用和Unikernel的Starry OS,进程如何定义便有了较为重要的意义。

我们先讨论了两种做法的优点:

  • 合并优点:符合Linux结构,更加直观
  • 分离优点:适配Unikernel实现,更加兼容ArceOS

为了得到更好的比较结果,我们分头行动,根据两种不同的定义方式实现了两个内核。经过比较之后,我们决定将进程和线程合并,更好地去适配ArceOS。

与ArceOS的兼容

为了保证和ArceOS代码功能上的兼容,在开发过程中需要一定程度地保留ArceOS原有代码,同时不能影响自己新的功能,防止出现冲突。

为了解决这个问题,我们用到了三种工具:

  • 条件编译

条件编译贯穿了Starry实现过程,通过指定不同的feature来定制不同的内核实现。同时,也可以用条件编译来在保留ArceOS原有功能的同时,添加上Starry的分支功能,指定不同的feature保证两者可以得到兼容。

cfg_if::cfg_if! {
    if #[cfg(feature = "monolithic")] {
        axprocess::process::init_kernel_process();
    }
    else {
        #[cfg(feature = "multitask")]
        axtask::init_scheduler();
    }
}
  • 封装trait

封装trait是Rust提供不同实现兼容的一种常见方式。不同结构通过用不同方式实现同一个trait,可以得到不同的处理方式和功能,从而达到了兼容并存的效果。如文件系统的一系列读写Trait便起到了这个功能。

  • crate_interface包

crate_interface包是由ArceOS实现的一个包,效果类似于trait。它允许用户在底层通过def_interface定义某些函数接口,并在上层通过impl_interface实现对应函数的具体内容。通过调用多个impl_interface便可以做到同一个接口的多种实现方式。

crate_interface与trait的一个不同之处在于,crate_interface的实现只能有一个,也就是说如果存在impl_interface,那么可能需要用到条件编译等手段使得仅有唯一一个impl_interface被实际编译到镜像中。

avatar