内存分配器
本节介绍堆内存分配器和物理页帧分配器
物理页帧分配
/// 使用bitmap_allocator库定义全局BIT_ALLOCATOR
static BIT_ALLOCATOR: Mutex<BitAlloc256M> = Mutex::new(BitAlloc256M::DEFAULT);
/// 初始化页帧分配器
pub fn init(memory_regions: &'static mut MemoryRegions) {
let mut ba = BIT_ALLOCATOR.lock();
println!("[Kernel] Memory regions:");
for region in memory_regions.into_iter() {
println!(" {:x?}", region);
if region.kind == MemoryRegionKind::Usable {
let start = region.start as usize;
let end = region.end;
let start_frame = start as usize / PAGE_SIZE;
let end_frame = end as usize / PAGE_SIZE;
ba.insert(start_frame..end_frame);
}
}
}
impl PhysFrame {
/// 分配一个物理页帧
pub fn alloc() -> Option<Self> {
allocate_frame().map(Self)
}
}
impl Drop for PhysFrame {
/// drop时释放掉物理页帧占的位
fn drop(&mut self) {
deallocate_frame(self.0);
}
}
我们使用了一个基于位图实现的物理页帧分配器,利用bootloader启动后传入的内存区域信息初始化位图。
物理页帧由内核显式地分配,需要一个新的页帧时使用alloc()
方法分配,而由编译器隐式地释放,释放时调用drop()
方法,释放掉页帧对应的bit。
堆内存分配
use buddy_system_allocator::Heap;
struct LockedHeap(Cell<Heap<32>>);
#[global_allocator]
static HEAP_ALLOCATOR: LockedHeap = LockedHeap(Cell::new(Heap::new()));
我们使用了一个带伙伴系统的堆内存分配器(来自第三方库),使用#[global_allocator]
将其注册为全局堆内存分配器。
#[global_allocator]
static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::empty();
#[alloc_error_handler]
pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! {
panic!("Heap allocation error, layout = {:?}", layout);
}
static mut HEAP_SPACE: [u8; KERNEL_HEAP_SIZE] = [0; KERNEL_HEAP_SIZE];
pub fn heap_init() {
unsafe {
HEAP_ALLOCATOR
.lock()
.init(HEAP_SPACE.as_ptr() as usize, KERNEL_HEAP_SIZE);
}
}
为其实现了GlobalAlloc
trait后,内核中即可使用动态内存结构,而具体内存分配和释放是由Rust编译器插入代码来实现的。