Introduction to IncludeOS

Introduction to IncludeOS

这是我和队友在 2019 年操作系统(H)课程中做的项目,这里做一个简单的回顾。

简介

Unikernel

传统内核都选择对硬件做了抽象,避免应用程序直接访问硬件资源,只提供抽象层提供的接口,例如 Linux 的应用程序全部运行在用户态,对硬件的操作全部通过系统调用进入内核态实现。这样做当然有好处,可以隐藏复杂的硬件细节,使用户专注于逻辑实现,但用户态和内核态之间的切换开销很大,损伤应用性能(在通常情况下影响不大,但对一些特殊场景,例如延迟敏感的 IoT 设备,会对影响性能)。

Unikernel 不区分用户态和内核态,所有应用都运行在同一层级,减少不必要的硬件抽象,(大多数 Unikernel)每次只运行一个应用,最大程度精简以提升性能表现。

当前社会,IoT 设备具有极大发展,具有很多有潜力的应用场景,我们希望在大量基于 ARM 架构的 IoT 设备上部署 Unikernel,因为 Unikernel 有如下优势:

  • 更高的运行性能;
  • 更高的资源利用效率;
  • 更好的隔离性和安全性;
  • 更好的可迁移性和可伸缩性。

但 Unikernel 也存在缺陷,最大的缺点就是调试非常困难。

经过调研,我们选择了 IncludeOS 作为基础的 Unikernel 实现,并将其移植到 ARM 上。

IncludeOS

  • 使用语言:C/C++;
  • 构建工具:Cmake + Conan;
  • 目前支持平台:x86/x86_64.

简单说一下 Conan,这是一个基于 Python 的 C++ 项目构建工具,它可以:

  • 自动安装需要的库(打包并根据包之间的依赖关系安装);
  • 能够将自己的包放到 remote server 上,方便别人可以使用 conan install 安装;
  • 跨平台,可以生成多种平台的构建系统配置文件,如 CMakeLists.txt.

构建过程简介

源代码结构如下:

Image

运行时结构如下:

Image

实际构建过程非常复杂,可以参考我们的 building doc 了解详细信息,这里大概阐述一下思路:

  • 安装 IncludeOS 意味着构建所有 OS 组件,这些组件使用 GNU AR 生成为一个静态库。我们需要显式地将需要的库加入 CMakeLists.txt 中,这样设备驱动将会以静态库的形式构建;
  • 最终只有所有必须的组件被链接到一起,转换为一个最小的 ELF 文件,作为 Unikernel。

我所做的一些工作

我在前期主要根据 LZT 同学完成构建,并和他一起进行了部分启动工作,之后我们分开行动,我完成了 GPIO, UART 以及 Framebuffer 的构建,具体的一些细节可以参考我们的 concluding.md

我们遇到的一些问题

最终我们的移植并没有在裸机上成功运行,研究发现是内存对齐出了问题。ARM 对内存对齐的要求很高,在 util::Lstack 中的部分代码没有整理,里面有很多强制类型转换,可能出现的 Alignment Fault 也没有完成修复,这也就是裸机暂时不可用的原因。

另外 QEMU 也并不检查内存是否对齐,这也导致我们在 QUME 上可以成功运行,但在裸机上却失败了。

本来想写网卡驱动,也是项目的主要目的之一,但是网卡依赖于 USB 驱动,USB 驱动非常复杂,而且又临近 DDL,我们最终还是没有成功。

我们的学习到的一些调试技术和手段

这次项目中也学到了一些调试技术和手段,对内核的调试还是比较麻烦,我们使用的是 QEMU + GDB/GDBGUI。

QEMU 支持远程调试,指定远程端口后暂停,之后连接 GDB server 进行远程调试,配合 GDBGUI 可以清晰展示函数调用、堆栈信息、寄存器信息等,调试体验还不错。

未来的工作展望

LZT 同学已经受邀整理我们的 AArch64 源码,在他不咕咕的情况下有希望 Merge 进 includeOS 的官方工作,为开源社区做一点微小的贡献。

打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2020 Bowen
  • Powered by Hexo Theme Ayer

请我喝杯咖啡吧~

支付宝
微信