需要实现
- 初始化堆
- malloc/calloc/free
..好像也没什么
rCoreBook里直接用了现成的堆管理器buddy_system_allocator, 不能自己跟着写一个了.
等有空(基本没空)的时候看看怎么实现一个堆管理器罢
看了Elegy的博客 大概是说malloc/calloc什么的也是要经过堆管理器的.
地址空间
- MMU
- PTE
- TLB
MMU: 内存管理单元
CPU取指令取地址之前, 地址经过MMU从虚拟地址转为物理地址
PTE: 页表项
标志位 + RSW(?) + ppn + 保留位
TLB: 快表.
缓存一部分映射,从而加快(跳过)三级映射的过程
分段内存管理
将程序所占的内存空间分配到物理内存中
或者更细粒度地,将程序分成多个段,不定顺序地分配到物理内存中.(复杂度很高)
这种做法没有内碎片,有外碎片
分页内存管理
上图更直观
尽量简单地来说:
程序和物理内存都有n个大小相同的段,并且有各自的id
mmu建立起两种id之间的对应关系.
cpu通过虚拟地址访问时, 虚拟地址的前半段为虚拟页号,会被转为物理页号.
其后半段是偏移量,这个不用转换.
页表内容也是存到内存中的一个页表里的!
riscv下如何管理内存
这里使用sv39, 即ppn有39位
satp: 一个64位csr寄存器^[状态和控制寄存器,比如mstatus表示在哪个态, mcause表示异常或中断的原因等.].
PPN:根页表所在的物理页号.
设置satp来启用分页模式.
vpn: 27, ppn: 44
多级页表
线性表: 一对一映射,有很大一部分空间被浪费(因为未被使用)
引入多级页表(比如3级):查找的工作细分到最后一级页表.
一级页表的ppn占9位,2^9=512,可表示512个次级页表项.
一个页表项8B,则一个页表4KiB.
如何实现多级页表?
先实现一个页帧分配器.
实现:new, alloc, dealloc(free).
1 | pub struct StackFrameAllocator { |
分配时,若recycle中没有已经被回收的页,则尝试分配新的页.
回收时,若页号合法,将回收的页号push到recycle中.
封装一个页帧类型FrameTracker,并为其实现new和Drop:
1 | pub struct FrameTracker { |
然后考虑页表的实现:
1 | pub struct PageTable { |
每个页表都存储了其对应的页帧(包括它本身. 前面提到了页表本身的内容也是存到它自身指代的某个页帧里的,这里是放到frames[0]了.)
map/unmap VPN/PPN
也就是绑定和解绑vpn到ppn的映射.
建立时,查找每级页表中有没有对应下一级的vpn页表,没有就创建. 然后将物理地址放到第三级页表中.
解绑就是清空第三级页表的对应物理地址.
1 | pub fn map(&mut self, vpn: VirtPageNum, ppn: PhysPageNum, flags: PTEFlags) { |