原方式为 线段树、
改为 线性数组
有什么变化:
不理想的变化:运行效率变低、看起来不够那么fashion、放弃了一些优化的想法、
理想的变化:肉眼可见的简单、逻辑清晰、易于理解、对第一次接触学习人员的友好、属于蛮力算法、
总结:侧重点不同、添加线性数组方式、为了继续降低初次学习这方面知识人员的学会阈值、
详细内容(废话)如下↓
- 可用物理内存地址
- 物理页帧大小
- 可用物理页数目
- 把目前未被组织起来的物理内存地址资源、用结构组织起来、叫做初始化、
- 把已组织起来的资源、建立分配规则、
- 把已组织起来的资源、建立收回规则、
前提: 当我们把资源组织起来后、我们所拥有的能力是:
- 连续的物理页号
- 通过物理页号能对应的物理地址范围
目的:把资源用数据结构组织起来、结构化后、方便后续的使用
问题:
- 用什么结构
- 怎么组织
思考过程:
- 看需求选择数据结构
- 目前的情况是、物理内存就在那里、就像一排排椅子、在一个有序的活动中、怎么坐是有规则的、不能想坐哪里坐哪里、我们要管理人员落座、需要一个本本、记录一下情况、哪里已经坐人了、哪里没坐人、哪里能坐、哪里不能坐、都要明明白白的、现在就是要初始化这么一个本子、
目的:分配出去一个物理页帧
问题:
- 分配哪一个页帧
- 怎么分配、
- 有什么输入、
- 有什么输出、
思考过程:
-
分配哪一个物理页、好像都没什么关系、因为还有上一层的虚拟地址、所以无差别看待物理地址、于是可以选择只要是能分配的就分配出去就好。
-
怎么分配、通过物理页帧号、去计算分配一个地址、
-
需要有什么?应该不需要、
-
需要有什么输出么、需要、需要给出去页帧号
目的:回收一个指定的物理页帧
问题:
- 怎么回收
思考过程:
- 理论上我们在本子上把占用的状态改一下就好了
pub struct LinearArrayAllocator {
ppns : [u8;MAX_PHYSICAL_PAGES],
offset:usize,
}
ppns就是我们的线性数组了、一共有最大的物理页帧数大小、这就是我们上文所说的小本子了、
offset是有一些说法的、因为我们的物理地址不是从0开始的(物理地址开始的位置是0x80_200_000、)、offset的值是以物理地址为参考的、而我们定义的本子范围确是从0开始计算、所以也不麻烦、加上一个偏移就好了、或者需要理解为y=ax+b中的b、很有用、
一、init
pub fn init (&mut self,l:usize,r:usize)
pub fn init (&mut self,l:usize,r:usize) {
self.offset = l-1; // 计算出偏移值
let usedppn= MAX_PHYSICAL_PAGES+l-r; // 计算之前有多少已被占用
for i in 0..usedppn { // 把已被占用的页帧记录上
self.ppns[i] = 1;
}
}
我们接收一个需要初始化的页帧号范围[l,r)、左闭右开、 (这时是物理地址参考)
offset被设置为l-1、是表示物理地址从0开始要偏移这么多、下一个才到达可用的首个页号
因为我们的规矩、默认了有一些内存地址不可用、比如被kernel占用的空间、当我们接收到可用的地址时、在记录的本子上、必然不能在第一页就开始写字、这是用上offset调整到正确的位置、是必要的、
回到我们本子上的序号、实际情况是比(l-物理地址开始的位置的)页号还小的页号都已经被占用了、
接下来我们在本子上、把已被占用的位置都标记上1、当作已占用的意思。
这样基本上就简单的初始化完成了、
我这个表达可能不够好、但事实确实这样的事、关键要分清、实际的物理空间、和我们本子上的序号、
(offset的值包含了我们kernel的页帧号的范围)
二、 alloc
pub fn alloc (&mut self) -> usize
pub fn alloc (&mut self) -> usize {
let mut freeppn = 0;
for i in 0..MAX_PHYSICAL_PAGES {
if self.ppns[i] == 0 {
freeppn = i + self.offset;
self.ppns[i] = 1;
break;
}
}
if freeppn == 0 {
panic!("physical memory depleted!");
}
freeppn
}
当我们要分配一个页帧出去时、我们要看哪里可以分配、很纯粹的想法、如果我们顺序的找可用的资源、找到第一个给出去就好了、
定义一个freeppn代表要分配出去的可用页帧号、初始值为0、但0号必不可用、所以最后要给出去时、看一眼freeppn是否还是0、如果是那么就表示、目前可能没有可用的页帧号了、也就是满了、
接下来我们在整个本子上查找、看看哪个页空闲、可以被分配出去、本子上值为0就代表可用、找到后、加上个偏移值、就是应该被分配出去的页号了、
二、 dealloc
pub fn dealloc (&mut self,n: usize)
pub fn dealloc (&mut self,n: usize) {
let p = n - self.offset;
self.ppns[p] = 0;
}
外面接受一个要被收回的页帧号、
我们用这个页帧号减去偏移值
然后在设置本子上、可用、就基本结束了
总体上没多少东西、想把过程写出来看上去有点多、表述能力训练不够、望大家捡有用的看吧、