From b5bd4bfee78d8481ce1daa2de7e3c69c22910c02 Mon Sep 17 00:00:00 2001 From: zhangxinyu <840317537@qq.com> Date: Thu, 8 Jun 2023 13:47:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E5=86=85=E6=A0=B8?= =?UTF-8?q?=E6=A0=88=E5=92=8Cpid=E7=BB=93=E6=9E=84=E4=BD=93,=20=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E5=8D=95=E7=8B=AC=E7=AE=A1=E7=90=86=E6=AF=8F=E4=B8=AA?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E7=9A=84=E5=86=85=E6=A0=B8=E6=A0=88,=20?= =?UTF-8?q?=E5=92=8C=E5=AF=B9=E5=BA=94=E7=9A=84PID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ch5/os/src/config.rs | 12 ---- ch5/os/src/main.rs | 2 +- ch5/os/src/task/mod.rs | 1 + ch5/os/src/task/pid.rs | 122 ++++++++++++++++++++++++++++++++++++++++ ch5/os/src/task/task.rs | 3 +- 5 files changed, 126 insertions(+), 14 deletions(-) create mode 100644 ch5/os/src/task/pid.rs diff --git a/ch5/os/src/config.rs b/ch5/os/src/config.rs index 08d870f..2bf0d55 100644 --- a/ch5/os/src/config.rs +++ b/ch5/os/src/config.rs @@ -11,15 +11,3 @@ pub const TRAMPOLINE: usize = usize::MAX - PAGE_SIZE + 1; // __alltraps对齐 pub const TRAP_CONTEXT: usize = TRAMPOLINE - PAGE_SIZE; // 用户 trap context开始的位置 在 每个用户程序 它本身地址空间 的次高页 pub use crate::board::*; - - - -/// 得到 "用户程序的内核栈" 的在 内核本身地址空间 中的虚拟位置(当然由于恒等映射其实也是实际的物理地址) -/// 这个在 跳板的下面的某个位置 -/// 每个用户除了分配 KERNEL_STACK_SIZE 大小外, 还额外 增加 一个PAGE_SIZE 放在比栈底要高的地址 用来隔离每个用户内核栈 -pub fn kernel_stack_position(app_id: usize) -> (usize, usize) { - let top = TRAMPOLINE - app_id * (KERNEL_STACK_SIZE + PAGE_SIZE); - // 栈底只需要 KERNEL_STACK_SIZE 即可, - let bottom = top - KERNEL_STACK_SIZE; - (bottom, top) -} diff --git a/ch5/os/src/main.rs b/ch5/os/src/main.rs index 6040ca4..59a869f 100644 --- a/ch5/os/src/main.rs +++ b/ch5/os/src/main.rs @@ -51,7 +51,7 @@ pub fn rust_main(){ // 初始化动态内存分配器, 使我们能在内核中使用动态大小数据类型 mm::init(); use loader; - loader::list_apps(); + println!("{:?}", loader::get_app_data_by_name("00power_3")); // trap::init(); // trap::enable_timer_interrupt(); // 允许定时器中断 diff --git a/ch5/os/src/task/mod.rs b/ch5/os/src/task/mod.rs index 255bccb..98ae6b2 100644 --- a/ch5/os/src/task/mod.rs +++ b/ch5/os/src/task/mod.rs @@ -13,6 +13,7 @@ use crate::trap::TrapContext; mod context; mod switch; mod task; +mod pid; // 公开到外部的一个全局任务管理器的结构体 diff --git a/ch5/os/src/task/pid.rs b/ch5/os/src/task/pid.rs new file mode 100644 index 0000000..2f4dcd0 --- /dev/null +++ b/ch5/os/src/task/pid.rs @@ -0,0 +1,122 @@ +use alloc::vec::Vec; +use lazy_static::lazy_static; +use crate::config::{KERNEL_STACK_SIZE, PAGE_SIZE, TRAMPOLINE}; +use crate::mm::memory_set::{KERNEL_SPACE, MapPermission}; +use crate::sync::UPSafeCell; + +// pid分配器 +pub struct PidAllocator { + current: usize, // 当前分配到多少号了 + recycled: Vec, // 被回收的pid, 后续可以再次利用 +} + +// 全局的pid分配器 +lazy_static! { + pub static ref PID_ALLOCATOR: UPSafeCell = + unsafe { UPSafeCell::new(PidAllocator::new()) }; +} + +impl PidAllocator { + pub fn new() -> Self { + Self { + current: 0, + recycled: Vec::new(), + } + } +} + +impl PidAllocator { + // 分配一个pid + pub fn alloc(&mut self) -> PidHandle { + if let Some(pid) = self.recycled.pop() { + PidHandle(pid) + } else { + let current = self.current; + self.current += 1; + PidHandle(current) + } + } + + // 取消分配一个pid + pub fn dealloc(&mut self, pid: usize) { + assert!(pid < self.current); + // 防止二次释放 + assert!( + !self.recycled.iter().any(|tmp_pid| *tmp_pid == pid), + "pid {} has been deallocated!", + pid + ); + + self.recycled.push(pid); + } +} + + +// 用来表示进程的唯一标识符, RAII思想来进行释放管理 +pub struct PidHandle(pub usize); + +// pid_handle 被drop时, 同时把pid 还给全局管理器 +impl Drop for PidHandle { + fn drop(&mut self) { + PID_ALLOCATOR.exclusive_access().dealloc(self.0); + } +} + + +/// 得到 "用户程序的内核栈" 的在 内核本身地址空间 中的虚拟位置(当然由于恒等映射其实也是实际的物理地址) +/// 这个在 跳板的下面的某个位置 +/// 每个用户除了分配 KERNEL_STACK_SIZE 大小外, 还额外 增加 一个PAGE_SIZE 放在比栈底要高的地址 用来隔离每个用户内核栈 +/// 根据 pid 在相应的位置, 得到app 内核栈的它处于的位置, 位置, 注意代码实现, 这个是有保护页面的(1 pagesize), +/// 在逻辑地址空间存在保护页面(保护页面不会被映射), 但是在物理地址空间,这个保护页会被随时被物理页帧管理器分配走 +/// 返回的 top是内存的高地址, bottom是内存的低地址 +pub fn kernel_stack_position(pid: usize) -> (usize, usize) { + let top = TRAMPOLINE - pid * (KERNEL_STACK_SIZE + PAGE_SIZE); + // 栈底只需要 KERNEL_STACK_SIZE 即可, + let bottom = top - KERNEL_STACK_SIZE; + (bottom, top) +} + +// 新的结构体, 内核栈, 之前我们是根据 app_id 找到的, 现在我们需要改成 统一分配的pid, 根据pid摆放应用内核栈的位置 +pub struct KernelStack { + pid: usize, +} + +impl KernelStack { + // push 一个 泛型, 到 内核栈中, 直接减去T的大小, 再写入即可 + pub fn push_on_top(&self, value: T) -> *mut T { + let kernel_stack_top = self.get_top(); + let kernel_stack_top = self.get_top(); + let ptr_mut = (kernel_stack_top - core::mem::size_of::()) as *mut T; + unsafe { + *ptr_mut = value; + } + ptr_mut + } + + // 得到当前内核栈的 栈底(高地址) + pub fn get_top(&self) -> usize { + let (_, kernel_stack_top) = kernel_stack_position(self.pid); + kernel_stack_top + } +} + +impl KernelStack { + // 根据 pid handle 在内核空间(最高页的下面) 某个位置, 创建一个 逻辑段 作为应用的内核栈 + pub fn from(pid_handle: &PidHandle) -> Self { + let pid = pid_handle.0; + + let (kernel_stack_bottom, kernel_stack_top) = kernel_stack_position(pid); + KERNEL_SPACE + .exclusive_access() + .insert_framed_area( + kernel_stack_bottom.into(), + kernel_stack_top.into(), + MapPermission::R | MapPermission::W, + ); + KernelStack { pid: pid_handle.0 } + } +} + + + + diff --git a/ch5/os/src/task/task.rs b/ch5/os/src/task/task.rs index 90569f5..46c9eaa 100644 --- a/ch5/os/src/task/task.rs +++ b/ch5/os/src/task/task.rs @@ -1,8 +1,9 @@ -use crate::config::{kernel_stack_position, TRAP_CONTEXT}; +use crate::config::{TRAP_CONTEXT}; use crate::mm::address::{PhysPageNum, VirtAddr}; use crate::mm::memory_set::{KERNEL_SPACE, MapPermission, MemorySet}; use crate::println; use crate::task::context::{TaskContext}; +use crate::task::pid::kernel_stack_position; use crate::trap::{trap_handler, TrapContext}; // TCB的字段, 用来保存任务的状态