-
Notifications
You must be signed in to change notification settings - Fork 387
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #150 from neoming/master
finish blog for `rCore lab1-3`
- Loading branch information
Showing
1 changed file
with
65 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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之后,直接通过! |