宏内核
到宏内核的特点就是:
- syscall
- app和kernel分离
- 特权级分离
- 独立空间
- 可以加载应用
用户空间降级方式:伪造返回现场到新任务, sret
过程:
- 初始化用户栈
- 创建新任务
- 让出CPU
几个重要的点
1. 任务扩展属性
将调度属性和资源属性分离,从而复用调度组件

2. 系统调用
用的是linkme这个库linkme
是一个 Rust 的库,主要用于在编译期将数据链接到程序的特定部分(如全局变量),从而实现类似插件或模块化的功能。它可以动态扩展程序的功能,而无需显式修改原始代码。以下是对 linkme
的详细介绍,包括其用法和原理。
核心功能
linkme
提供了一种机制,使多个 Rust 模块中的静态变量可以被聚合到一个全局列表中。常见的使用场景包括:
- 插件系统:收集并注册动态功能。
- 初始化系统:在程序启动时执行一系列初始化函数。
- 静态配置集合:在不同的模块中定义配置项,并将它们汇总到一个位置。
使用方法
1. 添加依赖
在Cargo.toml
中添加:1
`[dependencies] linkme = "0.3"`
2. 定义集合
使用 #[linkme::distributed_slice]
定义一个全局的切片,用于收集静态变量。例如:
1 | use linkme::distributed_slice; |
这里,MY_SLICE
是一个切片,它的类型是 fn()
,表示可以存放多个函数指针。
3. 添加元素
在其他模块中,使用 #[distributed_slice]
将元素插入到切片中:
1 | use linkme::distributed_slice; |
4. 使用切片
在程序中,你可以遍历切片的所有元素,并执行对应逻辑:
1 | fn main() { |
得到
1 | First function |
原理解析
linkme
的实现基于 Rust 的链接器特性和目标平台的支持。以下是其工作原理:
- 分布式切片的定义:
#[distributed_slice]
宏定义了一个全局符号,分配了一段内存区域,专门用于存储相关的元素。
- 分段存储:
- 每次使用
#[distributed_slice]
添加元素时,linkme
会将这些元素放置到编译产物的特定段(section)中。
- 每次使用
- 链接器聚合:
- 链接器在链接阶段会将所有模块中定义的元素合并到一个段中,使得这些元素在运行时可以统一访问。
课后题
- 注册 PAGE_FAULT
- 完善注册函数
- 获得当前的task
- 得到aspace
- 调用其handle_page_fault方法填充
第二节
内存管理方式:

其他的和rcore很像,最后会在backend中处理映射
- alloc(支持lazy)
- linear (连续映射)
lazy映射:先map出虚拟地址但是没有关联物理地址,在page fault后在处理函数中多次嵌套调用handle,最后在aspace中完成关联
课后题
mmap的实现和page fault的处理很像,
- 找到一个free的va(最开始这里卡了很久)
- 读取文件内容,填充到buffer
- map alloc出一个页
- 用buffer填充这个页
hypervisor
第一节
hypervisor和虚拟机的区别是:支撑其物理运行的体系结构和其虚拟运行的环境是否一样(同构). 所以hypervisor比虚拟机更加高效.
我的理解,hypervisor也是一种类似于OS软件,如果是U的指令可以直接执行,如果需要特权级就在hypervisor中捕获处理.
hypervisor的扩展指令也是为了加速这个过程
资源管理:
- vcpu(直接绑定到一个CPU)
- vmem(提供自己的页表转换)
- vdevice(virtual io/ 直接映射 / 模拟)
- vutilities(中断/总线..)
练习题
panic将系统shut,所以需要去掉panic改成(ax_println!),然后将sepc+4跳转到下一个指令,再设置一下a0,a1的值就可以了
第二节
主要学习了两段映射
- Guest缺页,guset os向hypervisor查找
- hypervisor也缺页,向实际物理机申请
第二的部分有两个模式
- 透传
- 模拟
透传:直接把宿主物理机(即qemu)的pflash透传给虚拟机。(快 捆绑设备)
模拟:模拟一个pflash,当读取的时候传递(慢 不依赖硬件)
切换
具体的汇编:
练习题
将pflash.img写入img的/sbin/下后,在 h_2_0/src/main.rc
中将其read出来,然后将第一页的内容填充到buf中,aspace.write进去就可
第三节课
实验课正在做
虚拟时钟
总的思路是:通过关键的寄存器hvip中的VSTIP(时钟中断)来向hypervisor响应虚拟机的设置时钟中断,然后当时钟中断来的时候退出vm,并重新设置时钟中断hvip,回到vm处理.
宏内核的支持
主要是flash这种设备的处理,这个在前一个的实验中已经解决了.
虚拟设备管理:通过mmio,注册device的地址,当发生page fault的时候判断一下,如果是在mem中则正常处理,如果是在device则去对应的设备处理.