全局的内存管理器完成
parent
c583719ad0
commit
c239525dc4
@ -0,0 +1,73 @@
|
||||
use crate::config::{PAGE_SIZE, PAGE_SIZE_BITS};
|
||||
|
||||
const PA_WIDTH_SV39: usize = 56; // 真实物理地址 的字节宽度 44(物理页宽) + 12(4kb的宽度)
|
||||
const PPN_WIDTH_SV39: usize = PA_WIDTH_SV39 - PAGE_SIZE_BITS; // 物理页 的宽度, 也就是 物理地址宽度-每页宽度=物理页宽度
|
||||
|
||||
|
||||
// 物理地址
|
||||
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub struct PhysAddr(pub usize);
|
||||
|
||||
// 虚拟地址
|
||||
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub struct VirtAddr(pub usize);
|
||||
|
||||
// 物理页
|
||||
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub struct PhysPageNum(pub usize);
|
||||
|
||||
// 虚拟页
|
||||
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub struct VirtPageNum(pub usize);
|
||||
|
||||
|
||||
// 把usize 转为真实地址(只保留 PA_WIDTH_SV39 位字节)
|
||||
impl From<usize> for PhysAddr {
|
||||
fn from(v: usize) -> Self { Self(v & ( (1 << PA_WIDTH_SV39) - 1 )) }
|
||||
}
|
||||
|
||||
// 把usize类型的物理页号 转为物理页结构体 (只保留物理页的宽度)
|
||||
impl From<usize> for PhysPageNum {
|
||||
fn from(v: usize) -> Self { Self(v & ( (1 << PPN_WIDTH_SV39) - 1 )) }
|
||||
}
|
||||
|
||||
// 把物理地址转为 usize, 直接返回即可
|
||||
impl From<PhysAddr> for usize {
|
||||
fn from(v: PhysAddr) -> Self { v.0 }
|
||||
}
|
||||
|
||||
// 把物理页结构体转为 usize类型的物理页 直接返回即可
|
||||
impl From<PhysPageNum> for usize {
|
||||
fn from(v: PhysPageNum) -> Self { v.0 }
|
||||
}
|
||||
|
||||
|
||||
impl PhysAddr {
|
||||
// 从当前物理地址得到页内偏移(只保留12个bit即可)
|
||||
pub fn page_offset(&self) -> usize {
|
||||
self.0 & (PAGE_SIZE - 1)
|
||||
}
|
||||
|
||||
// 舍去小数位, 把物理地址, 转为 物理页号
|
||||
pub fn floor(&self) -> PhysPageNum {
|
||||
PhysPageNum(self.0 / PAGE_SIZE)
|
||||
}
|
||||
|
||||
// 有小数统一 +1, 物理地址转为物理页号
|
||||
pub fn ceil(&self) -> PhysPageNum {
|
||||
PhysPageNum((self.0 + PAGE_SIZE - 1) / PAGE_SIZE)
|
||||
}
|
||||
}
|
||||
|
||||
// 把PhysAddr 转为 PhysPageNum
|
||||
impl From<PhysAddr> for PhysPageNum {
|
||||
fn from(v: PhysAddr) -> Self {
|
||||
assert_eq!(v.page_offset(), 0);
|
||||
v.floor()
|
||||
}
|
||||
}
|
||||
|
||||
// 把物理页转为物理地址(左移页宽即可)
|
||||
impl From<PhysPageNum> for PhysAddr {
|
||||
fn from(v: PhysPageNum) -> Self { Self(v.0 << PAGE_SIZE_BITS) }
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
use alloc::vec::Vec;
|
||||
use lazy_static::lazy_static;
|
||||
use crate::mm::address::{PhysPageNum, PhysAddr};
|
||||
use crate::config::MEMORY_END;
|
||||
use crate::sync::UPSafeCell;
|
||||
|
||||
extern "C" {
|
||||
fn ekernel();
|
||||
}
|
||||
|
||||
// 物理页帧管理器, 它管理了 ekernel(操作系统使用的内存结束位置) 到 MEMORY_END(最大的可用的物理内存地址)所有的内存, 这部分内存是给用户用的
|
||||
// current, end 这个区间表示此前从未被分配过的页
|
||||
// recycled 表示之前被分配过, 但是已经被回收可以再利用的页
|
||||
pub struct StackFrameAllocator {
|
||||
current: usize,
|
||||
end: usize,
|
||||
recycled: Vec<usize>,
|
||||
}
|
||||
|
||||
impl StackFrameAllocator {
|
||||
fn from(l: PhysPageNum, r: PhysPageNum) -> Self {
|
||||
Self {
|
||||
current: l.0,
|
||||
end: r.0,
|
||||
recycled: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StackFrameAllocator {
|
||||
// 从分配器中, 找到一个空闲页(它可能之前从未分配过, 或者之前被分配但是已经被回收的完好页)
|
||||
fn alloc(&mut self) -> Option<PhysPageNum> {
|
||||
if let Some(ppn) = self.recycled.pop() {
|
||||
Some(ppn.into())
|
||||
} else if self.current == self.end {
|
||||
None
|
||||
} else {
|
||||
self.current += 1;
|
||||
Some((self.current - 1).into())
|
||||
}
|
||||
}
|
||||
|
||||
// 回收一个页, 为了防止二次回收, 我们这里直接panic
|
||||
fn dealloc(&mut self, ppn: PhysPageNum) {
|
||||
let ppn = ppn.0;
|
||||
// 防止被二次回收
|
||||
if ppn >= self.current || self.recycled.iter().any(|&v| v == ppn) {
|
||||
panic!("Frame ppn={:#x} has not been allocated!", ppn);
|
||||
}
|
||||
// 校验完毕, 把这个页, 还给管理器
|
||||
self.recycled.push(ppn);
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref FRAME_ALLOCATOR: UPSafeCell<StackFrameAllocator> = unsafe {
|
||||
// 这里我们只要完整的页, 舍去开头和结尾一些碎片
|
||||
UPSafeCell::new(StackFrameAllocator::from(PhysAddr::from(ekernel as usize).ceil(), PhysAddr::from(MEMORY_END).floor()))
|
||||
};
|
||||
}
|
||||
|
@ -1 +1,3 @@
|
||||
pub mod heap_allocator;
|
||||
pub mod address;
|
||||
pub mod frame_allocator;
|
Loading…
Reference in New Issue