-
Notifications
You must be signed in to change notification settings - Fork 10
template 解析
在 main.rs
定义了程序的入口 main
(在启动阶段由 polyhal 跳转至此),中断的处理函数 interrupt_handler
。以及一个 trait
PageAlloc
的实现 PageAllocImpl
.
#[polyhal::arch_entry]
pub fn main(hart_id: usize) {
println!("run default @ {}", hart_id);
crate::allocator::init_allocator();
crate::logging::init(Some("trace"));
println!("init logging");
// Init polyhal with page alloc, This init will init every platform
polyhal::init(&PageAllocImpl);
// get hardware available memory regions
get_mem_areas().into_iter().for_each(|(start, size)| {
println!("init memory region {:#x} - {:#x}", start, start + size);
crate::frame::add_frame_range(start, start + size);
});
println!("[kernel] exited successfully");
}
main 函数上有一个属性宏 #[polyhal::arch_entry]
,这个标识 main
函数是程序的入口,main
函数有一个参数 hart_id
,当从 polyhal
进入到这个函数时会携带当前的核心 id
。
println
是在 logging.rs
中定义的一个实现,可以输出信息。 polyhal
的 init
函数需要 kernel
支持 rust
的 GlobalAlloc
功能来使用 alloc
库下的一些东西,所以在调用 polyhal::init
之前需要先对 alloc
进行初始化。crate::logging::init
主要用于调试信息的输出,对 polyhal
的使用并无影响。然后就可以使用 polyhal::init
函数来完成 polyhal::init
的最终初始化。(可能你会感到奇怪,为什么不在 main
函数之前完成 polyhal
的初始化,可以参考 为什么需要 polyhal::init
函数)
在初始化之后我们就可以使用 polyhal
的全部功能了,比如我们可以通过 get_mem_areas
函数来获取平台的可用内存范围。获取到内存范围后就可以将可用内存范围传递给 kernel
管理内存的模块,这里是调用 crate::frame::add_frame_range
来初始化内存。
#[polyhal::arch_interrupt]
fn interrupt_handler(ctx: &mut TrapFrame, trap_type: TrapType) {
println!("trap_type @ {:x?} {:#x?}", trap_type, ctx);
}
interrupt_handler
函数在内核发生中断或者异常的时候被调用,首先会在 polyhal
中的处理程序首先处理和封装,然后再调用这里的函数。ctx
是中断发生的上下文,trap_type
是中断发生的类型,具体信息可以参考 polyhal
的文档。
struct PageAllocImpl;
impl PageAlloc for PageAllocImpl {
fn alloc(&self) -> polyhal::addr::PhysPage {
crate::frame::frame_alloc()
}
fn dealloc(&self, ppn: polyhal::addr::PhysPage) {
crate::frame::frame_dealloc(ppn)
}
}
在介绍 main
函数的时候我们已经描述过了,我们需要实现一个 PageAlloc
Trait
,然后在 polyhal::init
的时候将实现传递给 polyhal
,alloc
为申请一个物理页,目前支持的物理页大小为 4KB
,且这里申请的物理页仅在 dealloc
的时候才会被释放(TIPS: 如果在相应的物理页结构上实现了 Drop
, 可能会产生一些异常行为)。