Skip to content

Commit

Permalink
Add blog.
Browse files Browse the repository at this point in the history
  • Loading branch information
Foreverhighness authored Dec 4, 2024
1 parent d678ab9 commit a220ddd
Showing 1 changed file with 95 additions and 0 deletions.
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 了,会快上不少。

0 comments on commit a220ddd

Please sign in to comment.