From 046cfc341b187895f4925f5b8d8efeae6c95d424 Mon Sep 17 00:00:00 2001 From: neoming Date: Sat, 4 Nov 2023 12:59:52 +0800 Subject: [PATCH] finish blog --- ...3-\346\235\216\344\270\200\351\270\243.md" | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 "source/_posts/2023\345\274\200\346\272\220\346\223\215\344\275\234\347\263\273\347\273\237\350\256\255\347\273\203\350\220\245\344\270\200\344\272\214\351\230\266\346\256\265\346\200\273\347\273\223-\346\235\216\344\270\200\351\270\243.md" diff --git "a/source/_posts/2023\345\274\200\346\272\220\346\223\215\344\275\234\347\263\273\347\273\237\350\256\255\347\273\203\350\220\245\344\270\200\344\272\214\351\230\266\346\256\265\346\200\273\347\273\223-\346\235\216\344\270\200\351\270\243.md" "b/source/_posts/2023\345\274\200\346\272\220\346\223\215\344\275\234\347\263\273\347\273\237\350\256\255\347\273\203\350\220\245\344\270\200\344\272\214\351\230\266\346\256\265\346\200\273\347\273\223-\346\235\216\344\270\200\351\270\243.md" new file mode 100644 index 00000000000..10d1dd3348d --- /dev/null +++ "b/source/_posts/2023\345\274\200\346\272\220\346\223\215\344\275\234\347\263\273\347\273\237\350\256\255\347\273\203\350\220\245\344\270\200\344\272\214\351\230\266\346\256\265\346\200\273\347\273\223-\346\235\216\344\270\200\351\270\243.md" @@ -0,0 +1,65 @@ +--- +title: 2023开源操作系统训练营一二阶段总结 +date: 2023-11-04 12:00:00 +categories: + - report +tags: + - author:neoming + - summerofcode2023 + - rcore-lab +--- + + + + +感谢老师和主教们提供的精彩课程,让我作为一个已经工作的工程师,在业余时间也能够深刻学习操作系统这门课程。课程内容丰富,技术前沿,把`RUST`, `RISCV` 和`OS`结合在一起,并且提供了完整的实验。经过学习我对操作系统有了很清楚的认识,虽然目前才做完lab3,但是后续会接着把两个实验也给完成。 + + +### lab1 + + + +实现`sys_task_info`的系统调用,首先要为`TaskControlBlock`添加两个对应字段: +```rust +TaskControlBlocl{ + /// ... + first_launch_time: Option, + syscall_times: [usize; MAX_SYSCALL_NUM] +} +``` +之后只要实现对应函数去正确更新这两个字段的值就可以了。 +1. 首先是用`Option`去记录`first_launch_time`,如果是`None`,则用当前的时间去赋值,这样就可以在每次`Task`调度的时候去记录`first_launch_time`。 +2. 在每次进入`sys_call`处理函数的时候去更新`syscall_times`。因为处理的时候可以获取到对应的`syscall_id`。 +### lab2 + +重写sys_get_time 和 sys_task_info两个系统调用是提醒我们返回值是写在虚拟地址的,所以需要做一次内存转换才把返回值写道正确的物理地址当中。主要使用了`rCore`提供的`translated_byte_buffer`拿到指向物理地址的内存,再把正确的结果写到内存即可。这里也加深了对`rust`中`unsafe`的理解。 + +实现`sys_mmap`和`sys_munmap`,主要是对`TaskControlBlock`中的`memory_set`进行修改。`memory_set`本身提供了`insert_framed_area`但是没有提供`remove_framed_area`,所以照着实现了一下。之后就可以按照是要求去更新`memory_set`,比较有意思的是要增加`MapPermission::U`。 +```rust +impl MemorySet{ + /// Remove framed area + pub fn remove_framed_area(&mut self, start_va: VirtAddr, end_va: VirtAddr) { + let mut target_area = + MapArea::new(start_va, end_va, MapType::Framed, MapPermission::empty()); + + target_area.unmap(&mut self.page_table); + self.areas + .retain(|area| area.vpn_range.get_start() != target_area.vpn_range.get_start()) + } +} +``` +### lab3 + +还是首次体验`git cherry-pick`,再次感谢清华提供的优秀课程,质量真的很高!`sys_get_time, sys_task_info, sys_mmap, sys_munmap`的实现都类似,实现`sys_spawn`我仔细读了`fork, exec`的代码,很自然就做出来了。 + +问题来到了`Stride`调度算法的实现上,一开始觉得逻辑不复杂,就是添加`TaskControlBlock`的`stride`字段,然后从队列中找到`stride`最小的执行。但是执行起来就发现有死循环,仔细读了文档发现还提到了时间片的概念。所以新增了`time_slice`字段,并且更改了调度逻辑,每次时间中断触发之后会先更新`time_slice`再决定进步进行调度。实现过程中也发现了`min_stride`的逻辑有问题,一开始认为`stride`最大值等于`BIG_STRIDE`,实际并不是。 +```rust + let mut min_stride = BIG_STRIDE;// Bug! should use usize::MAX + for tcb in self.ready_queue.iter() { + let cur_stride = tcb.inner_exclusive_access().stride; + if min_stride > cur_stride { + min_stride = cur_stride; + } + } +``` +当实现完`slice`和修复`min_stride`的BUG之后,直接通过!