0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

面向对象的Rust微内核介绍

yzcdx 来源:OS与AUTOSAR研究 2022-12-30 11:53 次阅读

前面介绍的rCore操作系统:rCore入门-来自清华的OS前沿教程,是清华的教学OS,相当于使用Rust语言山寨了下Linux,是一个宏内核

之前我有一篇文章介绍了微内核:seL4微内核入门-微内核介绍,相对来说微内核在学术上更严谨先进一些,尽管性能不如宏内核,其他方面有点多,特别是安全性

所以清华又搞了一个zCore思路还是山寨,这次瞄上了谷歌Fuchsia的Zicron微内核,见之前的文章Fuchsia入门-简介和代码介绍,总结下:

rCore:使用Rust语言山寨宏内核Linux

zCore:使用Rust语言山寨微内核Zicron

注意:这里说的山寨不是完全参考,不同语言也全参考不了,实现方式有很多不同之处。

上图是王润基同学恶搞了下谷歌Fuchsia的发布,改成自己的了真是新iPhone还没出来山寨就有了。

总结下,这些OS其实都有一个技术指向:Rust+微内核

谷歌的Fuchsia比较难产,所以逼急了又推出来一个KataOS,见之前文章:KataOS入门-简介和代码编译,直接用现成的seL4微内核+Rust应用框架Sparrow搞了。

回归正题,

1. zCore简介

161c3c48-7625-11ed-8abf-dac502259ad0.png

zCore 是用 Rust 语言重新实现的 Zircon 微内核

它运行在内核态,对外提供与 Zircon 完全相同的系统调用,因此能够运行原生的 Fuchsia 用户程序

之前的文章介绍过Fuchsia的强大,其应用程序更是兼容了安卓,另外对于微内核驱动也是应用,也可以应用Fuchsia强大的驱动程序。可见这个zCore的巨大应用价值。

2. 面向对象的内核

1661b214-7625-11ed-8abf-dac502259ad0.png

Zicron是用c++写的,更适合用Rust重写。有一个问题:什么时候需要面向对象?

假如世界上只有一个上帝,那就不需要面向对象。但是世界上还有几亿的人,人都有非常多的共性,那答案就是有很多个实例的时候就需要面向对象。

回到内核,第一直觉是进程,这东西是多个的,特别是用户进程,这必须可以面向对象啊,然后IPC通信,有很多进程直接又很多个通道通信,很多个就又可以面向对象。

凡是可以有多个的东西,都可以面向对象

c语言编写的内核或者宏内核中,经常用到抽象出来的结构体,多个的表达就是结构体数组或者结构体链表,其辅助处理函数都要自己写,例如查找插入改变值等,很繁琐

然后所有的东西都往进程结构体PCB里面塞,很多机制理解起来很费力,要去看那个很大的PCB结构体去理解,一下就懵了

人还是容易理解抽象出来的事物然后加上简单的思维逻辑,不抽象的混乱思维一会就晕了。

Zircon 是一个基于对象的内核

下面带你领略下面向对象的魅力,真是轻松学内核的法宝。先来看一个zCore内核运行时组件层次框架图:

1691c288-7625-11ed-8abf-dac502259ad0.png     

大家知道一般程序处理的流程:用户程序-》系统调用-》内核-》硬件里面去处理。

上图中红框里面就是把内核里面跟硬件无关的元素抽象出来,用面向对象的方法表示出来。

例如系统里面有多个Process,一个Process实例里面有很多个Handle和Rights指向其他的对象。

16c3852a-7625-11ed-8abf-dac502259ad0.png

内核对象相关的三个重要概念:对象(Object),句柄(Handle),权限(Rights)。

对象(Object)具备属性和行为的客体。客体之间可有各种联系。从简单的整数到复杂的操作系统进程等都可看做对象,它不仅仅表示具体的事物,还能表示抽象的规则、计划或事件。

句柄(Handle)标识对象的符号,也可看成是一种指向对象的变量(也可称为标识符、引用、ID等)。

权限(Rights):是指对象的访问者被允许在对象上执行的操作,即对象的访问权限。当对象访问者打开对象的句柄,该句柄具有对其对象的访问权限的某种组合。

说下我的理解,内核的资源都被抽象成对象,对象之间用句柄产生联系,这种联系为了安全性有权限限制,当没有句柄指向的对象也就是没用了会被收回。

用户程序操作内核对象的一些细节:

创建:每一种内核对象都存在一个系统调用来创建它,例如zx_channel_create。创建对象时一般需要传入一个参数选项 options,若创建成功则内核会将一个新句柄写入用户指定的内存中。

使用:获得对象句柄后可以通过若干系统调用对它进行操作,例如zx_channel_write。这类系统调用一般需要传入句柄 handle 作为第一个参数,内核首先对其进行检查,如果句柄非法或者对象类型与系统调用不匹配就会报错。接下来内核会检查句柄的权限是否满足操作的要求,例如 write 操作一般要求句柄具有 WRITE 权限,如果权限不满足就会继续报错。

关闭:当用户程序不再使用对象时,会调用zx_handle_close关闭句柄。当用户进程退出时,仍处于打开状态的句柄也都会自动关闭。

总之,面向对象的代码很清晰,很容易理解,不绕弯子,利用面向对象的语法,代码行数能大大缩减,预计5倍以上。上面的介绍大部分都是zCore教程里面的,这个教程更加的干货,直接介绍核心概念,对OS基础知识进行了省略。同rCore教程一样也是从零开始自己写一个OS的教程,这个感觉做的更好。

16fb9cd0-7625-11ed-8abf-dac502259ad0.png

3. rCore整体架构

zCore的设计主要有两个出发点:

内核对象的封装:将内核对象代码封装为一个库,保证可重用

硬件接口的设计:使硬件与内核对象的设计相对独立,只向上提供统一、抽象的API接口

项目设计从上到下,上层更远离硬件,下层更接近硬件,架构如下图所示:

1723492e-7625-11ed-8abf-dac502259ad0.png

为了让 zCore 能够同时运行在内核态和用户态,我们在最下面设计了一个硬件抽象层(HAL),将内核所依赖的底层操作封装起来,在裸机环境和 Linux/macOS 环境上分别提供不同的实现。 在 HAL 之上的核心是zircon-object,也就是 Zircon 内核对象,这里面包含了所有内核机制的实现。

在对象层之上是系统调用层,它负责将内核对象的功能封装成 Zircon syscall ABI 暴露给用户进程。 再往上就是整个 OS 的顶层模块,它负责完成系统初始化和加载第一个用户进程的工作,并将所有模块组装到一起,生成一个可执行文件。 zCore 设计的顶层是上层操作系统,比如 zCore、rCore、ZirconLibOS 和 Linux LibOS。

在项目架构中,各版本的操作系统有部分公用代码。与 zCore 微内核设计实现相关的部分则主要是图中左侧蓝色线部分。

乍一看,真是四不像,有点像嫁接,共用一个根,嫁接上不同的枝条,枝条上可以结出不同的水果。感觉这就是程序的高级玩法,殊途同归,万法归一,还能相互转化,实在是高,万能工具啊。好处是,这几种OS上的应用都可以在zCore上运行,跟吃了几种水果一样甜啊。

4. OS界的变形金刚

不仅如此,它还可以作为一个普通的用户进程运行在 Linux 或 macOS 的用户态,我们一般把这种模式称为 LibOS 或 User-Mode OS。你甚至无需安装 QEMU 模拟器,只需装上 Rust 官方工具链,就可以编译运行体验 zCore!

git clone https://github.com/rcore-os/zCore --recursive
cd zCore
git lfs pull
cargo run --release -p zircon-loader prebuilt/zircon
既然可以用户态运行,那么它其实就是一个普通的用户程序。这带来了巨大的好处:我们可以在用户态开发,用 gdb 配合 IDE 调试,用cargo test 跑单元测试,统计测试覆盖率……这在之前的内核开发中是难以想象的。

17c3a37e-7625-11ed-8abf-dac502259ad0.png    

zCore 作为 rCore 的继承者,它并没有把前辈丢掉。事实上,zCore 并不是一个独立的 OS,在它的仓库里还藏着一个小 rCore!只需使用以下命令,即可快速把它召唤出来,我们来运行一个原生 Linux 程序——Busybox:
make rootfs
cargo run--release-plinux-loader/bin/busybox
17f189c4-7625-11ed-8abf-dac502259ad0.png     

这里面的奥秘在于,Zircon 作为微内核,其实已经提供了内核中最关键的内存管理和进程管理的功能。

我们只需在它基础上补充 Linux 作为宏内核的其它功能(例如文件系统),并对外提供 Linux 系统调用接口,即可重新构造出一个新的 rCore。

这就是微内核运行宏内核程序的关键,缺的东西再加一层壳子,再封装一层系统调用。

5.编程语言分析

1836c32c-7625-11ed-8abf-dac502259ad0.png

官方 Zircon 是用 C++ 语言编写的,代码量约有 10w 行。而 zCore 只用了1w 行 Rust 就实现了其中大部分核心功能。虽然我们还差一些没有实现,但相差一个数量级的规模还是让我感到有些诧异。

不过至少据我观察,C++ 的 Zircon 代码从设计上就比较复杂,用了各种自己造的轮子,并且充斥着魔法操作。相比之下,Rust 的 zCore 代码看起来更加自然,核心库自带的基础设施再加上一些社区库的辅助,用起来还是非常舒服的。

关于 Rust 大家更关心的另一个话题unsafe。在 zCore 中我们尽量避免了 unsafe 的使用,但没有绝对禁止(毕竟禁止就写不出来了)。

据统计,在 HAL 之上大约有 20 个 unsafe,其中大部分用在了两个对象之间互相取 Weak 引用的操作,剩下的也比较容易检验正确性。

而 HAL 之下 unsafe 就比较多了,由于贴近底层硬件,几乎处处 unsafe,也就跟 C 没什么区别了。不过好在 HAL 代码还是比较少的,不过几百行而已。

Rust 唯一的问题就是门槛太高了。然而对于编写内核这种对性能、稳定性、安全性都要求极高的程序而言,门槛高一点未必是坏处。

在被 Rust 编译器反复教做人之后,才知道自己当初太天真,写出来的程序处处是隐患。

async 机制除了上面提到的用户态运行之外,zCore 还有一大创新之处:首次在内核中引入了 async 无栈协程机制。

熟悉主流编程语言的朋友会知道,async 是近几年开始流行的一种语言特性,能够让开发者用同步的风格编写异步代码。它本质上是将代码变换成状态机,在 OS 线程的基础上又提供了一层轻量级的“协程”,使得程序能够高效处理异步 IO,同时保持开发的高效率。

Rust 语言于 2019 年底正式稳定了 async-await 语法,并于今年 3 月份的PR#69033中为 no_std 环境下使用 async 扫清了障碍。

这使得在内核中全面应用 async 机制成为了可能,而 zCore 可能是第一个吃螃蟹的人。(C++20 中也引入了同样的特性,不过考虑到历史包袱和生态问题,我比较怀疑能否真正用起来)

在传统 OS 中,每个内核线程需要有自己独立的内核栈。当线程挂起时,它的状态就保存在栈上。

由于内核线程可能很多,因此每个线程的栈都不能太大,在 Linux 中一般是两个页也就是 8KB。而在 zCore 中,所有内核线程都变成了协程,在一个 CPU 核上共享同一个内核栈。

当进入用户态时,内核栈不再清空,因为要保留必要的信息,于是内核-用户切换的风格从传统的「用户态中断调用内核处理函数」变成了「内核主动调用函数切换到用户态执行」。

当任务挂起时,协程的状态被包装成 Future 存储在堆上。根据计算,目前每个 Future 状态机的大小约为 600B 左右,大幅节省了内存空间。

无栈协程相比线程的好处除了空间占用少以外,还有更小的上下文切换开销,进而实现更高的并发和吞吐率。

不过它的缺点在于协作式、不可抢占,这可能会为系统的实时性带来挑战。关于二者之间的对比,还有待进一步的测试和分析。

zCore 的主要特性和创新点:

第一个完全山寨的 Zircon 内核

使用 Rust 编写,实现精简,层级清晰

支持用户态开发、测试和运行

第一个在内核中使用 async 机制

总的来说,zCore 应该是目前为止我们能想到、做到的,Rust 语言操作系统的集大成之作了。

6. 代码下载体验

已经运行过rCore环境的机器,可以直接下载zCore的代码体验下。

下载命令:

Git clone https://github.com/rcore-os/zCore.git
编译运行命令:
cargo qemu --arch riscv64
还是基于RISC-V硬件的qemu虚拟机运行:

189a7a70-7625-11ed-8abf-dac502259ad0.png






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 模拟器
    +关注

    关注

    2

    文章

    818

    浏览量

    42698
  • GDB调试
    +关注

    关注

    0

    文章

    23

    浏览量

    1390
  • HAL库
    +关注

    关注

    1

    文章

    112

    浏览量

    5894
  • Rust
    +关注

    关注

    1

    文章

    223

    浏览量

    6387

原文标题:zCore入门-面向对象的Rust微内核

文章出处:【微信号:OS与AUTOSAR研究,微信公众号:OS与AUTOSAR研究】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    labview面向对象编程

    点击学习>>《龙哥手把手教你学LabVIEW视觉设计》视频教程使用LabVIEW面向对象编程方法,对于大型测试应用程序来讲,面向对象相对于面向
    发表于 11-24 11:01

    面向对象的程序设计

    面向对象的程序设计
    发表于 08-18 21:04

    关于面向对象

    本帖最后由 sthhhh 于 2016-8-5 15:32 编辑 请问现在已有一个程序,如果要把这个程序改为面向对象编程可以吗?我需要怎么做?书上介绍面向
    发表于 08-05 14:22

    请问什么是面向对象

    什么是面向对象
    发表于 01-16 18:19

    LabVIEW面向对象编程入门介绍

    LabVIEW面向对象编程入门介绍类库描述介绍
    发表于 11-20 10:51

    LabVIEW面向对象的ActorFramework(1)

    ` 本帖最后由 bollworm 于 2020-2-10 14:54 编辑 本系列文章主要阐述以下几个问题:(1)什么是面向对象编程?(2)为什么要学习面向编程?(3)LabVIEW面向
    发表于 02-10 14:09

    LabVIEW面向对象的ActorFramework(2)

    二、为什么要学习面向编程?面向对象编程,如果将上文推荐的两本书读完后,基本上也就有了答案。从从自我产品开发的经验中,理解为可以迅速解决中大型程序需求变化时,在不影响其他程序功能的情况下,能够实现新增
    发表于 02-18 09:20

    Labview面向对象的思考方式

    面向过程和面向对象编程的思维方式用把大象装进冰箱来描述1、面向过程的思维方式:第一步:打开冰箱门第二步:把大象推进去第三步:关上冰箱门2、面向
    发表于 04-16 14:02

    谈谈面向对象编程

    在工业自动化领域,梯形图逻辑仍然是最常用的编程语言之一,但对于更加复杂的控制对象面向对象编程不失为一种高效率的方式。下面先来谈谈面向对象
    发表于 09-08 07:47

    面向对象编程语言的特点

    在工业自动化领域,梯形图逻辑仍然是最常用的编程语言之一,但对于更加复杂的控制对象面向对象编程不失为一种高效率的方式。下面先来谈谈面向对象
    发表于 09-08 07:44

    面向对象编程总结

    如何从面向过程到面向对象OOP?面向对象是什么?有何特点?
    发表于 09-29 08:19

    面向对象编程介绍

    目录一、面向对象编程介绍1.面向过程编程2.函数式编程3.面向对象编程二.
    发表于 12-13 07:22

    基于Rust基础上如何去编写一个Linux内核模块

    编者按:近些年来 Rust 语言由于其内存安全性和性能等优势得到了很多关注,尤其是 Linux 内核也在准备将其集成到其中,因此,我们特邀阿里云工程师苏子彬为我们介绍一下如何在 Linux
    的头像 发表于 08-27 09:59 3016次阅读

    Linux内核中整合对 Rust 的支持

    Linux Plumbers Conference 2022 大会上举行了一个 Rust 相关的小型会议,该会议讨论的大方向大致为:正在进行的使 Rust 成为一种合适的系统编程语言的工作,以及在主线 Linux 内核中整合对
    的头像 发表于 09-19 11:06 986次阅读

    面向过程与面向对象的区别

    说起面向对象,大家可能会想到其他的,但是此对象非彼对象哈哈,不必惊慌,也特别好搞定。 在听到面向
    的头像 发表于 02-15 11:10 2187次阅读
    <b class='flag-5'>面向</b>过程与<b class='flag-5'>面向</b><b class='flag-5'>对象</b>的区别