0%

学习总结 - Blankke

rcore与arceOS可以理解成两种不同思路编写而来的内核,而内核基本原理上估计是不会有太大区别的。
抱着这样的想法,三阶段只给了3周的时间,我就直接上了。
因为内核赛的时候基本上是整个内核都写了一遍,除了文件系统是调ext4库了没有太管里面怎么实现的,其他的原理明白了做起来还是挺快的。
我不知道有什么荣誉准则要求,这话说起来其实挺不好的,但是我的准则是不管copy还是llm生成,只要我觉得下一次遇到一样的问题我能一眼看出来用这个方法解决,那我就觉得这个学习是有效的。
所以这次的arceOS学习我也是抱着这样的态度去做的,并且内核的学习实际上最重要的部分可能更是在于解决问题,也就是在针对特定问题的排查思路上。

rcore

rcore部分我本身没有记录很多,只记了一些学习rust的时候的笔记,毕竟rcore的代码量实在是太大了,想要全部理解需要花费大量时间。然后在完成练习的时候我还不知道要写blog,所以只有一点点感悟和笔记。

ch3

为什么在 TaskManager 中添加方法而不是直接返回 TaskControlBlock

这确实是 Rust 所有权系统的限制,与 C++ 有本质区别:
Rust 所有权问题:

1
2
3
4
5
6
// 这样的设计在 Rust 中是不可能的:
pub fn get_current_task_mut(&self) -> &mut TaskControlBlock {
let mut inner = self.inner.exclusive_access();
let current = inner.current_task;
&mut inner.tasks[current] // ❌ 编译错误!
}
  • inner 是一个临时变量,当函数返回时会被销毁
  • 返回的 &mut TaskControlBlock 引用了inner的内容
  • Rust 编译器检测到”悬垂引用”(dangling reference)问题

C++ vs Rust

1
2
3
4
5
// C++ 可以这样做(自己管理)
TaskControlBlock& TaskManager::getCurrentTask() {
auto lock = inner.lock();
return tasks[current_task]; // 返回引用,但锁可能已释放
}
1
2
3
4
5
6
7
8
9
// Rust 强制我们使用更安全的封装方法
impl TaskManager {
pub fn increment_current_syscall_count(&self, syscall_id: usize) {
let mut inner = self.inner.exclusive_access(); // 获取锁
let current = inner.current_task;
inner.tasks[current].increment_syscall_count(syscall_id);
// 锁在这里自动释放
}
}

Clone trait 和 new 方法的关系

  • Copy:浅拷贝,按位复制,用于简单类型(如整数)
  • Clone:深拷贝,可能涉及堆内存分配,用于复杂类型
    但添加 Vec<(usize, usize)> 后:
    1
    2
    3
    4
    5
    6
    pub struct TaskControlBlock {
    pub syscall_counts: Vec<(usize, usize)>, // Vec 不能实现 Copy
    }
    let vec1 = vec![1, 2, 3]; // 在堆上分配内存
    let vec2 = vec1; // 如果是 Copy,会有两个指针指向同一块内存
    // 当 vec1 和 vec2 都被销毁时,会导致 double free!
    原来的初始化方式不再适用:
    1
    2
    3
    4
    5
    // 旧代码 - 数组字面量初始化
    let tasks = [TaskControlBlock {
    task_cx: TaskContext::zero_init(),
    task_status: TaskStatus::UnInit,
    }; MAX_APP_NUM]; // ❌ 需要 Copy trait
    新的初始化方式:
    1
    2
    3
    4
    // 新代码 - 使用 core::array::from_fn
    let tasks: [TaskControlBlock; MAX_APP_NUM] = core::array::from_fn(|_| {
    TaskControlBlock::new(TaskContext::zero_init(), TaskStatus::UnInit)
    });

ch4

主要新建的函数有

1
2
3
4
5
6
7
8
9
/// Translate a user pointer to a mutable reference
pub fn translate_user_ptr<T>(ptr: *mut T) -> Option<&'static mut T> {
TASK_MANAGER.translate_user_ptr(ptr)
}

/// Translate a user pointer to a reference
pub fn translate_user_ptr_readonly<T>(ptr: *const T) -> Option<&'static T> {
TASK_MANAGER.translate_user_ptr_readonly(ptr)
}

内部使用页表进行翻译,获得的(可变)引用可以用unsafe的类指针操作直接修改内存。
mmap的实现与cpp的方法无异,只是对应的层级是task层,由taskmanager调用获取当前的task,当前的task使用mmap,所以mmap是task的类方法。

ArceOS

Unikernel

T1 print-with-color

这个看了一下,可以在log层打印,也可以直接改std。

1
2
3
4
5
6
arch = riscv64
platform = riscv64-qemu-virt
target = riscv64gc-unknown-none-elf
smp = 1
build_mode = release
log_level = warn

像这种信息就是在log层里打出来的,如果修改axlog模块的lib.rs,那么这些打印信息就会变色

1
2
3
4
5
6
7
8
9
10
11
12
13
/// axlog/lib.rs
/// Prints to the console, with a newline.
#[macro_export]
macro_rules! ax_println {
() => { $crate::ax_print!("\n") };
($($arg:tt)*) => {
$crate::__print_impl($crate::with_color!(
$crate::ColorCode::BrightGreen,
"{}\n",
format_args!($($arg)*)
));
}
}

但是根据题目要求,我们打印的那句话其实是axstd里面的,所以我其实只在这个macro.rs里添加了色号就可以了。

1
2
3
4
5
6
7
8
/// Prints to the standard output, with a newline.
#[macro_export]
macro_rules! println {
() => { $crate::print!("\n") };
($($arg:tt)*) => {
$crate::io::__print_impl(format_args!("\u{1B}[92m{}\u{1B}[m\n", format_args!($($arg)*)));
}
}

这是绿色

T2 support-hashmap

在axstd等组件中,支持collections::HashMap
先读了一下axstd,原本的情况是这样的

1
pub use alloc::{boxed, collections, format, string, vec};

这里有一个collections,是从alloc模块过来的,那么实际上是标准库里的(我认为就是内核环境不支持标准库的哈希表),所以要替换成一个自己实现的HashMap。
上网查了一下hashbrown是一个常用的哈希表实现(hashbrown n. 薯饼),所以添加了依赖,用这现成的模块。

1
2
axhal = { workspace = true }
hashbrown = { version = "0.14", default-features = false }

接下来就是在axstd/src里面添加一个collection.rs然后将对应使用过的函数都用hashbrown进行对应实现就可以了。注意new()一定需要有对应的实现否则报错找不到。

T3 bump-allocator

这个很简单。
当时内核赛的时候瞎装了一万个分配器到自己的内核中,经过痛苦的阅读代码后了解过buddy、slab、liballocator的分配原理,这个bump分配器简单看一下原理似乎是堆分配器。然后需要实现页分配以及细粒度的字节分配,也就是多层级的分配。那就跟linux的slab&buddy的做法差不多了。
代码中todo写的很明确,每一步需要干什么,不会漏掉隐秘的细节,不像当初写内核一样自己出一堆找不到的bug在后面回来找。

T4 rename-for-ramfs

ramfs就是一个最基础的文件系统,不需要回写,不需要驱动,基本上意思就是在内存里进行书写,关机后不会存下来,这个rename也不会再下次开机后保存下来。
学习正常的rename,以前从没看过底层的inode操作,都是直接调用ext_rename()就完工了,所以这次对照着加抄袭整了个版本。
明确这个操作是在ramfs模块下的就简单了,这是个结点操作,所以要在两个地方添加操作(这是我的做法),一个是impl VfsNodeOps for DirNode,一个是DirNode内部。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/// Renames a node from `src_name` to `dst_name` in this directory.
pub fn rename_node(&self, src_name: &str, dst_name: &str) -> VfsResult {
let mut children = self.children.write();

let node = children.get(src_name).ok_or(VfsError::NotFound)?.clone();

if children.contains_key(dst_name) {
return Err(VfsError::AlreadyExists);
}

// Remove from old name and insert with new name
children.remove(src_name);
children.insert(dst_name.into(), node);

Ok(())
}

fn rename(&self, src_path: &str, dst_path: &str) -> VfsResult {中可以照着别的函数写法形成模板,最后一步调用上面的rename就好了

Macro

宏内核部分比较熟悉也简单,就略写了。

T1 Page-fault

这也是老朋友了,这个提示很明显,在axhal/trap里面,很多异常的处理方法都写在其中了。

T2 mmap

这更是老朋友,xv6就做过这个实验,rcore也是有。根据posix标准从堆内存找到空闲位置,扩大堆空间。
这里评测环境错误很久没过差点以为是我的问题,所以自己添加了一个get_brk()函数,结果又在本地爆了,这个实验似乎就是让我们使用find_free_area就可以了,并没有按照posix标准去处理那么多flag,也没有匿名映射。
后面所以我又改成了最简单的版本

1
2
3
4
5
6
7
8
9
10
11
12
13
let start_addr = if addr.is_null() {
// Use find_free_area to find a suitable address
let hint = VirtAddr::from(0x10000000usize);
let limit = VirtAddrRange::from_start_size(aspace.base(), aspace.size());
aspace.find_free_area(hint, aligned_length, limit)
.ok_or(LinuxError::ENOMEM)?
} else {
VirtAddr::from(addr as usize)
};

// Map memory in user address space
aspace.map_alloc(start_addr, aligned_length, mapping_flags, true)
.map_err(|_| LinuxError::ENOMEM)?;

这属于有点ltp后遗症,写了linux的标准错误号。然后后面其实也处理了fd是-1且不是MAP_ANONYMOUS的情况。

Hypervisor

这个虚拟化有点超纲了,以前确实没见过这种虚拟机的做法。我想理解成用户进程,这样的话自己有一个cpu对象,用户进程的地址空间也是连续的,但是在内核中不连续。

T1 simple-hv

这个有两个退出原因(据悉是这样):
IllegalInstruction (非法指令异常)和 LoadGuestPageFault (Guest 页面错误),需要在vm_exit的时候判断这几次错误并处理。实际上操作的方法有点像写cpu,直接对epc等寄存器进行+4这样。这个错误原因估计还要下到trap模块才能判断,就是csr寄存器里会记录错误原因。
为了调试这几种原因,我先添了几句调试输出,没想到其实本来它的打印就是有输出的。
可以读到代码中期望的输出就是这两个寄存器要放正确的值,而这之前就不要有vmexit

1
2
3
4
5
6
7
8
let a0 = ctx.guest_regs.gprs.reg(A0);
let a1 = ctx.guest_regs.gprs.reg(A1);
ax_println!("a0 = {:#x}, a1 = {:#x}", a0, a1);
assert_eq!(a0, 0x6688);
assert_eq!(a1, 0x1234);
ax_println!("Shutdown vm normally!");
ctx.guest_regs.sepc += 4;
return true;

所以就在对应的错误处理处改0x6688和0x1234就可以,对应指令sepc+4跳过

T2 pflash

从上面为止练习题其实就做完了。说来非常惭愧,我参加训练营有点面向做题的学习,从rcore开始都是学习的目标就是做完所有练习题就收工了,觉得解决问题才是做这个训练营的精华。这个练习也是个示例,不用我做自己就是好的。所以后面学起来有点没有动力。
分析了一下运行指令,其实是先编译了u_3_0的内核,然后把内核的bin文件写进了disk.img里,最后make一个虚拟机出来。运行之后里面也是显示了两次ArceOS(虚拟机里运行了内核),然后从guest里面试图去读host
很好看的一点是在make u_3_0的时候直接编译,而运行虚拟机h_2_0的时候可以把log开成info,这样的话就可以看到那句 Starting virtualization…,以及是如何装载虚拟机到虚拟地址的。
内核赛的时候很惊讶,因为听说第一名的Starry Mix可以在里面运行xv6,让我直接震惊了。后面了解到StarryOS就是在arceOS基础上改的,现在我才知道原来就是基于了这样的Hypervisor模式,真的长知识了。

这次的学习rcore有点艰辛,因为是把一个操作系统内核给完成了,虽然也只是补充了syscall里面的函数,但是>把整体内核需要什么部件给摸索清楚了
出了有关rust语言特殊机制的bug,就看看别的函数是怎么写出规范的rust代码的,虽然看了文档后有个思路去写
那个函数,但是不知道怎么写时,参考周围代码就好多了,让我印象比较深的是,当一个结构体的对象要被调用>的时候,比如inner,通常需要加个exclusive_access()或者unwrap()等等,这个rust语言虽然没有像C语言>那么底层,但是感觉这么一写,就不会出现内存问题,很规范。再不会通常只能问大佬了哈哈哈。
在这个训练营,大佬云集,接触到了很多才学渊博的人,大家也来自不同的专业,有着不同的志向,也坚定了我>跨越专业去学习更多知识的信心。


title: 梦醒的学习记录
date: 2025-03-25 21:02:12
tags:
mathjax: true


今天重写了一遍rustlings,虽然在其他训练营已经写过了,但是这次依然有收获。比如我了解到了
match时的ref有什么作用,以及他和&的区别

2024三阶段总结

Unikernel

  • print_with_color

简单的利用ascll字符实现颜色

  • support_hashmap

看群内大佬讨论,就引了一个库

  • alt_alloc

这个难度不大,因为测例很简单。严格实现后我确实也不知道自己实现的正确与否

  • shell

原shell实现了有关rename的,rename我就直接调库了,然后通过创建文件、copy文件内容、删除原文件拼接除了mv的功能

  • 1115挑战(内存调度算法实现优化)

说来惭愧,我这个印象最深。我写了3次,第一次好像是80多,第二次直接没跑起来,第三次是链表指针不知道指到哪里去了….反正都没超过170,也就没提交….

宏内核

  • page_fault

难度适中? 感觉就是rcore上了一点

  • sys_map

就find_free_area然后read进去,虽然感觉用find_free_area找到的地方有些不符合man mmap的说明。

Hypervisor

第一次了解hypervisor具体是怎么操作、干了什么….涨知识了…

  • simple_hv

改一下guest的sepc,设置一下a0、a1的值

  • pflash设备模拟方式

一开始没有搞清gpa映射到hpa时,没有经过host的satp,导致在host中拿着pa当va来用,出现了问题。另外,在完成后,修改了一下pflash的内容,想要读u128转string输出,但是没想到,在对* u128解引用时,它居然会先读u128的高64位,导致映射时页面没对齐。

2024四阶段总结 - Starry-Next 项目二方向一 感想

仓库链接: https://github.com/yjymosheng/Starry-On-ArceOS/tree/main

最终 commit ID: 71650c57f8ef9a64a6bdf274d9890b5c0c96642d

目前进展:

已经完成的syscall

a

没有完成的syscall

b

个人感想 :

这时我第二次参加os训练营,第一次的时候连rcore都没有完成,这一次由于对syscall的理解不够,相比其他同学浪费了很多时间在img的调试上.

可能下一次就能拿到优秀学员证书了也说不定?一次更比一次强嘛

虽然我的四阶段的学习可能差强人意,但是对我来说算是打开了操作系统的大门,希望明年的操作系统大赛上,能够有新的突破.

通过这次训练营,我进行了第一次对操作系统的尝试,与还对系统调用有了更加全面的认识。编写一个自己的操作系统不再只是纸上谈兵,而是一种有希望实现的技术。回顾整个过程,既有苦涩,也有喜悦,更重要的是,这让我对操作系统这条路充满了信心和期待。

希望未来,我能够在操作系统道路上走得更远,探索更多未知的可能性!

实验总结

问答作业

荣誉准则

  1. 在完成本次实验的过程(含此前学习的过程)中,我曾分别与 以下各位 就(与本次实验相关的)以下方面做过交流,还在代码中对应的位置以注释形式记录了具体的交流对象及内容:

  2. 此外,我也参考了 以下资料 ,还在代码中对应的位置以注释形式记录了具体的参考来源及内容:

    我的参考资料:
    rCore-Tutorial-Book-v3
    https://zh.wikipedia.org/wiki/%E9%93%B6%E8%A1%8C%E5%AE%B6%E7%AE%97%E6%B3%95

  1. 我独立完成了本次实验除以上方面之外的所有工作,包括代码与文档。 我清楚地知道,从以上方面获得的信息在一定程度上降低了实验难度,可能会影响起评分。

  2. 我从未使用过他人的代码,不管是原封不动地复制,还是经过了某些等价转换。 我未曾也不会向他人(含此后各届同学)复制或公开我的实验代码,我有义务妥善保管好它们。 我提交至本实验的评测系统的代码,均无意于破坏或妨碍任何计算机系统的正常运转。 我清楚地知道,以上情况均为本课程纪律所禁止,若违反,对应的实验成绩将按“-100”分计。

总结

一直以来对OS非常感兴趣,通过本次的“代码调试”,熟悉了整个项目架构,并对OS有了进一步的深刻认识。在调试过程中不仅熟悉了OS,还对Rust语言有了更深入的认识。
本次实现的功能是打印任务信息:系统调用及调用次数,运行时间。
整体思路:在syscall入口处调用set_task_info方法。每调用一次系统调用,更新一次syscall_times和time。
踩的坑:需要注意Rust结构体与C结构体的区别,Rust编译器会对Rust中的字段进行重排序,以达到优化存储的目的。在OS中的结构体和user中的结构体字段要保持一致,否则会蛋疼:(
另外附图一张,表示我曾用心学习:)

笔记

第一题

应用分别出现:

  • PageFault in application, bad addr = 0x0 bad instruction = 0x804003a4 , kernel killed it.
  • IllegalInstruction in application, kernel killed it.
    使用的sbi版本是:RustSBI version 0.3.0-alpha.2

第二题

1.刚进入__restore时,a0代表kernel stack pointer , restore的两种使用场景:a.trap 恢复 b.创建新任务

2.处理了sstatus sepc sscratch。sstatus用于指定返回的特权级(SPP字段);sepc用于指定返回后执行哪条指令;sscratch存储着用户栈地址,U态程序要执行必须正确找到U态的栈地址。

3.application不会使用x4;x2已经被交换到了sscratch代表着用户栈指针

4.sp指向user stack , sscratch 指向kernel stack

5.__restore总状态切换在csrw sstatus,t0这行指令,sstatus中的SPP字段记录了陷入前的特权级,csrw sstatus,t0执行后,恢复到用户特权级。最后的指令sret ,指令返回用户程序,原因是该指令会从sepc中读取指令地址,并赋予pc寄存器,而U态的栈等已恢复好,sret临门一脚,步入U世界。

6.指令之前sp -> user stack , sscratch -> kernel stack ;指令后sp -> kernel stack, sscratch -> user stack。指令进入内核运行。并且用sscratch保存着U态的栈地址,从内核态返回即可用sscratch恢复用户态栈指针。

  1. csrrw sp,sccratch, sp是程序从U态进入S态的关键指令,sp指向内核栈。

荣誉准则

  1. 在完成本次实验的过程(含此前学习的过程)中,我曾分别与 以下各位 就(与本次实验相关的)以下方面做过交流,还在代码中对应的位置以注释形式记录了具体的交流对象及内容:

  2. 此外,我也参考了 以下资料 ,还在代码中对应的位置以注释形式记录了具体的参考来源及内容:

    我的参考资料:rCore-Tutorial-Book-v3

  3. 我独立完成了本次实验除以上方面之外的所有工作,包括代码与文档。 我清楚地知道,从以上方面获得的信息在一定程度上降低了实验难度,可能会影响起评分。

  4. 我从未使用过他人的代码,不管是原封不动地复制,还是经过了某些等价转换。 我未曾也不会向他人(含此后各届同学)复制或公开我的实验代码,我有义务妥善保管好它们。 我提交至本实验的评测系统的代码,均无意于破坏或妨碍任何计算机系统的正常运转。 我清楚地知道,以上情况均为本课程纪律所禁止,若违反,对应的实验成绩将按“-100”分计。

总结

地址空间映射这一章知识密度较高,反复看了几遍才基本弄懂,调试代码陆陆续续调试了3天。(还是太菜,菜就多练!)
简单总结下本章:在开启分页SV39分页之前,OS和都是直接访问物理地址,这给系统带来很多潜在的安全隐患,例如地址空间未隔离等。开启分页模式后,OS和用户代码中就都是虚拟地址了,需要通过页表和MMU进行转换,并且页表上的属性区分出了U和S,进行了权限和空间的隔离,分别在特权级和地址空间上保证了OS内核的安全,同时也保证了用户程序之间相互隔离,彼此空间不会重叠。(虚拟空间可以重叠,但通过页表映射后通常是隔离的,有种特殊情况是通过映射到相同的物理也实现内存共享)

另外为了OS在开启分页后能平滑的访问,对于OS采用的是恒等映射(虚拟页号=物理页帧)。而对于用户程序通常采用Framed映射,通过栈式页帧分配器分配页帧并和虚拟页号建立映射关系,动态生成页表及页表项,实现物理页帧的按需分配。

另外一个比较好的抽象是地址空间MemorySet,它作为任务的一部分,管理着页表及和逻辑区。在实现采用了RAIL机制,加上rust的所有权及drop trait自动实现页表项的释放。

笔记

第一题

最低的位则是标志位,它们的含义如下:
仅当 V(Valid) 位为 1 时,页表项才是合法的;
R/W/X 分别控制索引到这个页表项的对应虚拟页面是否允许读/写/取指;
U 控制索引到这个页表项的对应虚拟页面是否在 CPU 处于 U 特权级的情况下是否被允许访问;
G 全局页表项。这意味着即使是在上下文切换(例如,进程切换)之后,该页表项也不会被冲洗(flushed)或失效。简而言之,G位用于指示页表项在地址空间的多个上下文中保持有效。
A(Accessed) 记录自从页表项上的这一位被清零之后,页表项的对应虚拟页面是否被访问过;
D(Dirty) 则记录自从页表项上的这一位被清零之后,页表项的对应虚拟页表是否被修改过。

第二题

荣誉准则

  1. 在完成本次实验的过程(含此前学习的过程)中,我曾分别与 以下各位 就(与本次实验相关的)以下方面做过交流,还在代码中对应的位置以注释形式记录了具体的交流对象及内容:

  2. 此外,我也参考了 以下资料 ,还在代码中对应的位置以注释形式记录了具体的参考来源及内容:

    我的参考资料:rCore-Tutorial-Book-v3

  3. 我独立完成了本次实验除以上方面之外的所有工作,包括代码与文档。 我清楚地知道,从以上方面获得的信息在一定程度上降低了实验难度,可能会影响起评分。

  4. 我从未使用过他人的代码,不管是原封不动地复制,还是经过了某些等价转换。 我未曾也不会向他人(含此后各届同学)复制或公开我的实验代码,我有义务妥善保管好它们。 我提交至本实验的评测系统的代码,均无意于破坏或妨碍任何计算机系统的正常运转。 我清楚地知道,以上情况均为本课程纪律所禁止,若违反,对应的实验成绩将按“-100”分计。

实验总结

文件系统章节是我花时间最多的一个章节,时间主要花在了对文件系统的理解上,看源码也费了些时间。将细节通过在线文档整理如下图所示:
ch6 基础知识

问答作业

Root Inode 的作用:
文件系统的入口点:在类 Unix 文件系统中,root inode 是文件系统层次结构的根,即 / 目录。它是访问文件系统其余部分的起始点。
存储目录信息:root inode 存储了根目录下的文件和子目录的元数据,例如它们的名称、inode 编号、文件类型(文件或目录)等。
维护文件系统结构:root inode 作为文件系统结构的起点,确保了整个文件系统的组织性和可访问性。
权限控制:root inode 还包含了访问权限信息,用于控制对根目录及其下内容的访问。
如果 Root Inode 损坏:
如果 root inode 中的内容损坏,可能会发生以下情况:

无法访问文件系统:由于 root inode 是访问文件系统的入口,如果它损坏,可能会导致整个文件系统无法挂载,用户无法访问任何文件或目录。
数据丢失:虽然文件数据可能仍然存储在磁盘上,但如果 root inode 损坏,系统可能无法定位这些数据,导致数据看似丢失。
文件系统损坏:文件系统的元数据完整性对于文件系统的健康至关重要。root inode 损坏可能导致文件系统元数据不一致,进而导致整个文件系统损坏。
恢复困难:恢复损坏的 root inode 可能非常困难,可能需要专业的数据恢复工具和专业知识。

荣誉准则

  1. 在完成本次实验的过程(含此前学习的过程)中,我曾分别与 以下各位 就(与本次实验相关的)以下方面做过交流,还在代码中对应的位置以注释形式记录了具体的交流对象及内容:

  2. 此外,我也参考了 以下资料 ,还在代码中对应的位置以注释形式记录了具体的参考来源及内容:

    我的参考资料:rCore-Tutorial-Book-v3

  3. 我独立完成了本次实验除以上方面之外的所有工作,包括代码与文档。 我清楚地知道,从以上方面获得的信息在一定程度上降低了实验难度,可能会影响起评分。

  4. 我从未使用过他人的代码,不管是原封不动地复制,还是经过了某些等价转换。 我未曾也不会向他人(含此后各届同学)复制或公开我的实验代码,我有义务妥善保管好它们。 我提交至本实验的评测系统的代码,均无意于破坏或妨碍任何计算机系统的正常运转。 我清楚地知道,以上情况均为本课程纪律所禁止,若违反,对应的实验成绩将按“-100”分计。

荣誉准则

  1. 在完成本次实验的过程(含此前学习的过程)中,我曾分别与 以下各位 就(与本次实验相关的)以下方面做过交流,还在代码中对应的位置以注释形式记录了具体的交流对象及内容:

  2. 此外,我也参考了 以下资料 ,还在代码中对应的位置以注释形式记录了具体的参考来源及内容:

    我的参考资料:rCore-Tutorial-Book-v3

  3. 我独立完成了本次实验除以上方面之外的所有工作,包括代码与文档。 我清楚地知道,从以上方面获得的信息在一定程度上降低了实验难度,可能会影响起评分。

  4. 我从未使用过他人的代码,不管是原封不动地复制,还是经过了某些等价转换。 我未曾也不会向他人(含此后各届同学)复制或公开我的实验代码,我有义务妥善保管好它们。 我提交至本实验的评测系统的代码,均无意于破坏或妨碍任何计算机系统的正常运转。 我清楚地知道,以上情况均为本课程纪律所禁止,若违反,对应的实验成绩将按“-100”分计。


title: dream第二阶段总结
date: 2024-05-31 20:00:41
categories:
- 2024春夏季开源操作系统训练营
tags:
- author:Eternal60f3
- repo:https://github.com/Eternal60f3/2024-rcore-repo


很感谢这次训练营的主办方。我这学期准备考研,然后就也想这弄一个项目。为复试增加点东西。

rcore让我熟悉了gdb以及git的使用。借助vscode的插件也很方便的利用git来比对前后差异来debug。

对于这几个实验。

再看完ch3的文档,当时以为自己理解了,等实际去看代码的时候,发现自己理解个屁。又回到ch2分支,捋清楚ch2的代码之后,才搞懂ch3的实现。

实验4非常nice本来一开始一直没搞懂,为什么要设置 DiskInode 和 Inode 两层抽象,而不是一层,但实际开始写的时候突然意识到,这是对于fs资源保证只有一个人使用的管理。对于涉及到了锁的编程,以前没太写过,debug弄了好久。

实验5在群里和佬们交流了才搞懂该怎么弄,debug了也弄了好久。好在最后做出来了。

可惜,阶段三之后可能没啥时间弄了,得抓数学了。未来说不定还会来参加啦,哈哈哈。多谢清华给了这么好的学习机会