add some comment and update readme
This commit is contained in:
parent
3491062cbe
commit
b21c752d76
|
@ -4,7 +4,7 @@
|
|||
## 基于共享调度器的异步内核设计
|
||||
操作系统内核经历了几个主要的发展阶段,从裸机应用,批处理系统到多道任务系统,演变为至今主流的线程操作系统。这种系统基于线程的切换来调度任务;为了进一步提升性能,一些现代编程语言在应用层复用线程资源,提出了“协程的”的概念,节省任务调度的开销。
|
||||
在本项目中我们提出一种新的内核开发思想:由不同资源共享调度器,在操作系统层面提供协程。我们希望这种全新设计的内核在满足传统内核的易用性的同时,拥有着专有内核的高性能特点,“像风一样快”,因此取名**飓风内核**——**tornado-os**。
|
||||
|
||||
设计文档请参考[这里](https://qf.rs/2021/04/23/%E5%BC%82%E6%AD%A5%E5%86%85%E6%A0%B8%E7%9A%84%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%AE%9E%E7%8E%B0.html)
|
||||
## 如何运行
|
||||
依赖工具:
|
||||
+ Rust 环境(nightly-2021-03-01或以上)
|
||||
|
@ -36,3 +36,5 @@ just qemu user_task
|
|||
+ [异步virtio块设备驱动](https://github.com/HUST-OS/async-virtio-driver)
|
||||
|
||||
其中,`洛佳的异步内核实验室`中实现了一个**内核中的生成器语法**,非常有研究价值,欢迎访问博客[执行器与生成语义](https://qf.rs/2021/05/01/%E6%89%A7%E8%A1%8C%E5%99%A8%E4%B8%8E%E7%94%9F%E6%88%90%E8%AF%AD%E4%B9%89.html)
|
||||
另外,我们还初步实现了一款基于 Rust 语言异步语法的 virtio 块设备驱动库,并可以结合本项目以异步的方式运行块设备读写任务,详细内容请访问博客[异步版VIRTIO之块设备驱动实现](https://qf.rs/2021/05/26/%E5%BC%82%E6%AD%A5%E7%89%88virtio%E5%9D%97%E8%AE%BE%E5%A4%87%E9%A9%B1%E5%8A%A8%E5%AE%9E%E7%8E%B0.html)
|
||||
|
||||
|
|
|
@ -4,14 +4,14 @@ mod ring_fifo;
|
|||
pub use ring_fifo::RingFifoScheduler;
|
||||
|
||||
/// 调度器实例需要实现的 Trait
|
||||
///
|
||||
pub trait Scheduler<T: Clone + PartialEq> {
|
||||
/// 优先级的类型
|
||||
type Priority;
|
||||
/// 向调度器中添加一个任务,成功返回 None,不成功返回 Some(T)
|
||||
fn add_task(&mut self, task: T) -> Option<T>;
|
||||
/// 获取下一个任务的引用,但不弹出任务
|
||||
/// 获取下一个任务的不可变引用,但不弹出任务
|
||||
fn peek_next_task(&self) -> Option<&T>;
|
||||
/// 获取下一个任务的可变引用,但不弹出任务
|
||||
fn peek_next_task_mut(&mut self) -> Option<&mut T>;
|
||||
/// 弹出下一个时间段应当执行的任务
|
||||
fn next_task(&mut self) -> Option<T>;
|
||||
|
|
|
@ -23,6 +23,7 @@ impl<T, const N: usize> RingFifoScheduler<T, N> {
|
|||
|
||||
impl<T: Clone + PartialEq, const N: usize> Scheduler<T> for RingFifoScheduler<T, N> {
|
||||
type Priority = ();
|
||||
/// 添加任务
|
||||
fn add_task(&mut self, task: T) -> Option<T> {
|
||||
// 加入环形队列
|
||||
let ans = self.ring.push_back(task);
|
||||
|
@ -32,28 +33,34 @@ impl<T: Clone + PartialEq, const N: usize> Scheduler<T> for RingFifoScheduler<T,
|
|||
}
|
||||
None
|
||||
}
|
||||
/// 取出下一个任务,成功返回 Some(T)
|
||||
fn next_task(&mut self) -> Option<T> {
|
||||
// 从头部取出
|
||||
let ans = self.ring.pop_front();
|
||||
self.current = ans.clone();
|
||||
ans
|
||||
}
|
||||
/// 拿出下一个任务的不可变引用,不弹出
|
||||
fn peek_next_task(&self) -> Option<&T> {
|
||||
// 拿出头部的引用
|
||||
self.ring.front()
|
||||
}
|
||||
/// 拿出下一个任务的可变引用,不弹出
|
||||
fn peek_next_task_mut(&mut self) -> Option<&mut T> {
|
||||
self.ring.front_mut()
|
||||
}
|
||||
/// 获取当前任务
|
||||
fn current_task(&self) -> Option<T> {
|
||||
self.current.clone()
|
||||
}
|
||||
/// 移除一个特定的任务
|
||||
fn remove_task(&mut self, task: &T) {
|
||||
// 移除相应的线程并且确认恰移除一个线程
|
||||
drop(task);
|
||||
todo!("还没做")
|
||||
}
|
||||
/// 设置任务优先级
|
||||
fn set_priority(&mut self, _task: T, _prio: ()) {}
|
||||
/// 当前调度器的任务数,如果是队列实现则返回 Some(T)
|
||||
fn queue_len(&self) -> Option<usize> {
|
||||
Some(self.ring.len())
|
||||
}
|
||||
|
|
|
@ -45,7 +45,6 @@ pub fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
|
|||
}
|
||||
|
||||
// todo: 未来尽量使用有Allocator的new_in函数,这样能处理内存不足的问题
|
||||
|
||||
#[cfg_attr(not(test), alloc_error_handler)]
|
||||
pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! {
|
||||
println!("[shared scheduler] alloc error, layout = {:?}", layout);
|
||||
|
|
|
@ -2,6 +2,7 @@ use super::Allocator;
|
|||
use alloc::{vec, vec::Vec};
|
||||
use core::ops::Range;
|
||||
|
||||
/// 栈分配器
|
||||
pub struct StackedAllocator {
|
||||
list: Vec<Range<usize>>,
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ pub extern "C" fn rust_main(hart_id: usize) -> ! {
|
|||
|
||||
println!("Current hart: {}", hart::KernelHartInfo::hart_id());
|
||||
|
||||
// todo: 这里要有个地方往tp里写东西,目前会出错
|
||||
// todo: 这里要有个地方往tp里写东西,否则目前会出错
|
||||
let kernel_memory = memory::MemorySet::new_kernel().expect("create kernel memory set");
|
||||
kernel_memory.activate();
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ use riscv::register::{sepc, stval};
|
|||
use crate::{memory::{self, Satp}, trap::SwapContext};
|
||||
use crate::trap;
|
||||
use super::{SyscallResult, syscall};
|
||||
use alloc::vec::Vec;
|
||||
|
||||
/// 测试用的中断处理函数,用户态发生中断会陷入到这里
|
||||
pub extern "C" fn user_trap_handler() {
|
||||
|
|
|
@ -8,6 +8,7 @@ use core::{mem, task::{Poll, Context}};
|
|||
切换上下文时,要把上下文保存好,最终还是要回到切换的地方继续运行。
|
||||
*/
|
||||
|
||||
/// 内核态的执行器,不断轮询共享调度器中的任务
|
||||
pub fn run_until_idle(
|
||||
peek_task: impl Fn() -> TaskResult,
|
||||
delete_task: impl Fn(usize) -> bool,
|
||||
|
@ -17,9 +18,10 @@ pub fn run_until_idle(
|
|||
let task = peek_task();
|
||||
println!(">>> kernel executor: next task = {:x?}", task);
|
||||
match task {
|
||||
TaskResult::Task(task_repr) => { // 在相同的(内核)地址空间里面
|
||||
TaskResult::Task(task_repr) => { // 轮询到的任务在相同的(内核)地址空间里面
|
||||
set_task_state(task_repr, TaskState::Sleeping);
|
||||
let task: Arc<KernelTaskRepr> = unsafe { Arc::from_raw(task_repr as *mut _) };
|
||||
// 注册 waker
|
||||
let waker = waker_ref(&task);
|
||||
let mut context = Context::from_waker(&*waker);
|
||||
let ret = task.task().future.lock().as_mut().poll(&mut context);
|
||||
|
@ -33,8 +35,10 @@ pub fn run_until_idle(
|
|||
todo!("切换到 next_asid (= {}) 对应的地址空间", next_asid)
|
||||
},
|
||||
TaskResult::NoWakeTask => {
|
||||
// 当前共享调度器里面没有醒着的任务
|
||||
todo!()
|
||||
},
|
||||
// 没有任务了,退出
|
||||
TaskResult::Finished => break
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ use core::fmt;
|
|||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
/// 任务的信息
|
||||
// TODO: 只是内核任务,用户任务由用户自己定义表现方式
|
||||
// 如果要运行用户的进程,首先切换到用户的地址空间,其中包含一个初始化好的栈和剩余空间,然后在里面增加用户的任务
|
||||
pub struct KernelTask {
|
||||
/// 任务的编号
|
||||
|
@ -69,20 +68,6 @@ impl KernelTask {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq for KernelTask {
|
||||
fn eq(&self, other: &KernelTask) -> bool {
|
||||
self.id == other.id
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for KernelTask {}
|
||||
|
||||
impl core::hash::Hash for KernelTask {
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
self.id.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for KernelTask {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let inner = self.inner.lock();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use spin::{Mutex, MutexGuard};
|
||||
|
||||
/// 关闭中断的互斥锁
|
||||
/// 这个锁目前用不上,但先留着
|
||||
#[derive(Default)]
|
||||
pub struct Lock<T>(pub(self) Mutex<T>);
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ use alloc::sync::Arc;
|
|||
use core::future::Future;
|
||||
use core::ptr::NonNull;
|
||||
|
||||
// 创建一个新的内核任务,打包它的环境
|
||||
/// 创建一个新的内核任务,打包它的环境
|
||||
pub fn new_kernel(
|
||||
future: impl Future<Output = ()> + 'static + Send + Sync,
|
||||
process: Arc<Process>,
|
||||
|
|
|
@ -58,10 +58,7 @@ impl Process {
|
|||
};
|
||||
Some(process)
|
||||
}
|
||||
// /// 得到进程编号
|
||||
// pub fn process_id(&self) -> ProcessId {
|
||||
// self.id
|
||||
// }
|
||||
|
||||
/// 得到进程*所在*的地址空间编号。进程不*对应*地址空间编号
|
||||
pub fn address_space_id(&self) -> AddressSpaceId {
|
||||
self.inner.lock().memory_set.address_space_id
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use riscv::register::{stvec, sstatus::{self, SPP, Sstatus}, sepc, scause::{self, Trap, Exception}, stval};
|
||||
use core::fmt;
|
||||
use crate::{hart::KernelHartInfo, println};
|
||||
use crate::syscall::{SyscallResult, syscall as do_syscall};
|
||||
use super::timer;
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
use riscv::register::scause::{self, Trap, Interrupt};
|
||||
use riscv::register::{sepc, stval};
|
||||
|
||||
use crate::memory::{self, PAGE_SIZE};
|
||||
use crate::memory;
|
||||
use crate::trap;
|
||||
use crate::task;
|
||||
|
||||
|
|
Loading…
Reference in New Issue