Skip to content

Commit

Permalink
Merge pull request #150 from neoming/master
Browse files Browse the repository at this point in the history
finish blog for `rCore lab1-3`
  • Loading branch information
limingth authored Nov 4, 2023
2 parents 40e24bb + 046cfc3 commit c980493
Showing 1 changed file with 65 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -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,但是后续会接着把两个实验也给完成。
<!-- more -->

### lab1



实现`sys_task_info`的系统调用,首先要为`TaskControlBlock`添加两个对应字段:
```rust
TaskControlBlocl{
/// ...
first_launch_time: Option<usize>,
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之后,直接通过!

0 comments on commit c980493

Please sign in to comment.