增加了内核栈和pid结构体, 用于单独管理每个应用的内核栈, 和对应的PID
parent
a8bf43b113
commit
b5bd4bfee7
@ -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<usize>, // 被回收的pid, 后续可以再次利用
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局的pid分配器
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref PID_ALLOCATOR: UPSafeCell<PidAllocator> =
|
||||||
|
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<T: Sized>(&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::<T>()) 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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue