Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2024秋冬季开源操作系统训练营第三阶段总结-shj #672

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
title: 2024秋冬季开源操作系统训练营第三阶段总结-shj
date: 2024-11-31 11:11:11
categories:
- 2024秋冬季开源操作系统训练营第三阶段总结
tags:
- author: Foreverhighness
- repo: https://github.com/Foreverhighness/oscamp
---

## Submit Blog

`rcore-blog` 这个 repo 已经挺大的了,网不好的 clone 下来还挺费时间的。

实际上可以直接在 Github 上写东西提 PR 不需要本地 clone 下来,Github 网站本身就提供了这样的功能。

打开 [`rcore-blog`](https://github.com/rcore-os/blog) 项目主页,在绿色按钮 `Code` 左边有个 `Add file` 的按钮,可以直接用 `Create new file` 写所需要的 Blog 或者用 `Upload files` 直接上传写好的 md 文件。

需要注意的点是要切到 `rcore-blog/source/_posts` 这个目录下,不然文件的位置不对。

虽然直接在网站上写,文件里的内容还是要注意一下加上 Blog 需要的分类/标签/作者信息等,这些东西随便打开一个 md 文件复制一下就行。

缺点是数学公式支持和插入本地图片可能麻烦点。

注意一下 Commit changes 里上面是 Commit message, 下面只是辅助描述,一般只用改上面就行。

## print_with_color

引用了我很喜欢的一个库 `ansi_rgb`, 秒了。

## hashmap

在 axstd 里开个 `mod collections`, 再引入 `hashbrown`, 秒了,

## alt_alloc

测试里实际上没有用到 Page alloc 的接口,写完 Byte alloc 就通过了。

## rename and mv in shell

有意思的来了,实际上 `fs::ax_rename` 没有很好的处理 './' 和 '/' 这些前缀后缀。

我认为在 shell 的逻辑里处理文件访问文件名是一个错误的抽象,因此我写的时候决定不在 shell 代码里处理路径问题。

观察到 ls 命令可以处理前缀后缀,一路跳转后决定在 `modules/axfs/src/fs/fatfs.rs` 中 `DirWrapper::rename()` 中进行处理,刚好旁边就有 `remove` 方法可以参考。

## lab1

觉得没意思就没写,看群里大佬们玩挺花的,我自己想能不能玩点 hack, 最后确认到 main 地址是可以获取的,main 的 text 内存是可读可写的。

也就意味着可以整花活来跳转到自定义的 `main` 函数当中去,但是想到这样就要做 platform 的适配,感觉工作量并不小,就没整。

## set populating to false

从 `AddrSpace` 为入口开始找参考的辅助函数,发现直接就有 `handle_page_fault` 可以用,一调用就过了,看看 m2 的参考才知道 `user` flag 的作用。

## mmap

这个练习用到的 api 挺多,需要找找 `find_free_area`, `api::fs`, `LinuxError`, `AxError`.

因为 rust 没有 goto, 所以错误处理需要包一层 `fn() -> Result`, 这样才能用 `?` 来减少代码量。

`?` 只能在 `Result` 和 `Option` 上用就已经很强大了,如果 [`try_trait_v2`] 稳定了都不用包一层 fn 了,不敢想象有多爽。

[`try_trait_v2`]: https://rust-lang.github.io/rfcs/3058-try-trait-v2.html

# simple hypervisor

这个练习不错,有一定难度。

首先处理 `csrr a1, mhartid` 这条指令。

尝试了下直接用 `asm!("csrr {rd}, mhartid", out(reg) rd)` 进行代理,不过如我所料的是 hypervisor 也没有 M 权限,所以不能这样弄。

但是可以注意到 `mhartid` 的语义是 cpu id, 所以可以直接用 `axhal::cpu::this_cpu_id()` 的值就行。

不过事实上根据语义应当返回的值是 vcpu id, 也就是 hypervisor 让 Guest 看到的 cpu_id, 但是我懒得添加相关的逻辑了。

把值写到上下文的 `a1` 寄存器之后需要把 `spec` 也加上指令长度。

然后处理缺页,注意到 `src/task.rs` 里有 `TaskExt` 的定义,并且压根没用上,可以知道大概需要用上。

但是我偷懒没去用,而是直接改了 `vmexit_handler` 和 `run_guest` 的接口,加一个 `uspace` 参数,这样就能在 `vmexit_handler` 里修改页表了。

对于一个内核来说,所有内存地址都是可以访问的,所以直接用 `uspace.map_alloc()` 就行了,权限可以全加上。

一个很有意思的点是 hypervisor 寻址用的是 `satp`, Guest 机器寻址用的是 `hgatp`. 所以写入用 `uspace.write` 来进行。

## Emulator mode device

直接把注释去掉就能通,所以改起来挺简单的。把 `populate` flag 置为 false 会导致 `Supervisor Page Fault` 错误。

刚好文件里就直接给出了一个 `load_vm_image` 辅助函数,直接拿来用把参数改改就完成了。`size` 可以通过 `fs::metadata` 来获取。

之前提到过 aspace 目前不支持 File 类型的 Backend, 不然就可以把 `populate` 置为 false 了,会快上不少。