学习之前先加把油——现在就是最好的学习时间,不晚的,加油!⛽️!!!
在介绍内存池之前,我们先来介绍一下管理内存的数据结构位图
位图
众所周知,OS内存是一个大容量资源,也是一个稀缺资源,我们在进行管理的时候一方面要保证对其有效的管理,另一方面也要保证,其管理的数据结构占据的内存不能太大。 所以,我们需要一个数据结构,其用尽可能小的单位管理内存中尽可能大的内存,于是就有了我们的位图
这里我们简单介绍一下位图,让我们把重点放在创建内存池上。
位图其为一连串的二进制位,对于它的实现用的是字节数组,也就是其以字节为单位,一字节=8bit。
其通过用1bit的容量来管理内存中的每次进行数据交换的最小单位:页 —— 4KB,所以对于位图来说,我们对他的搜索方式为,先搜索在哪一字节,再搜索在字节中的哪一位,通过该为来完成对资源的管理。
让我们来看一下位图的结构
struct bitmap
{
unit32_t btmp_bytes_len;
unit8_t * bits;
};
其中btmp_bytes_len为字节数组的长度,注意如果要找到具体的位的话,需要进行 “ btmp_bytes_len/8 “
由于其实位图的长度是由内存的空间来决定的,因此,我们其实是无法提前预知的,所以我们需要一个bits字节型指针,使用它来记录位图的地址。
内存池的规划
也就是说当在实模式下
,逻辑地址给出后,其内存池在用户物理内存池中找到一个物理地址分配给这个逻辑地址。
当在保护模式下
,逻辑地址给出后,先给其在虚拟内存池中分配虚拟地址(这个地址不同进程间可以相同,也就仿佛是每个进程都拥有来4GB的大空间,但是,在同一个进程内,虚拟地址必然唯一,这通常由链接器对其进行分配),再从这些用户共享的物理内存池中分配对应的物理地址给这个虚拟地址。
废话不多说了,让我们直接来通过代码来理解吧。
?我们第一步要完成的任务:
1⃣️给我们的物理地址位图和虚拟地址位图找一个存放的空间
(因为我们要知道物理地址不具有连续性,虚拟地址是逻辑上的,具有联系性。所以我们通常分别对其进行管理)
2⃣️创建我们的用户物理内存池和内核物理内存池和内核虚拟内存池
(这里我们为了简便先不创建用户虚拟内存池)
3⃣️计算位图所占用的内存,算出剩余的内存和空闲页,来完成对用户和内核物理内存池的分配
?我们第二步要完成的任务
1⃣️给用户和内核物理池分配等分其剩余的空闲页
2⃣️分别对内存和用户物理内存池依照所定义的物理内存池结构进行初始化
结构如下:
struct pool
{
struct bitmap pool bitmap;
uint32_t phy_addr_start; //本内存池所管理物理内存的起始地址
uint32 t pool size; //本内存池字节容量
}
struct bitmap
{
unit32_t btmp_bytes_len;
unit8_t * bits;
};
及分别为用户和内核的这些变量赋值:phy_addr_start,pool size,btmp_bytes_len, bits
?我们第三步要完成的任务
1⃣️输出用户和内核的物理内存池信息
2⃣️根据物理内存池信息初始化虚拟内存池信息
虚拟内存池结构如下:
struct virtual_addr
{
struct bitmap vaddr ·bitmap; / /虚拟地址用到的位图结构
uint32_t vaddr_start; //虚拟地址起始地址
}
struct bitmap
{
unit32_t btmp_bytes_len;
unit8_t * bits;
};
及为内核的这些变量赋值:vaddr_start,btmp_bytes_len, bits
今天先简单介绍一下思路吧,以后有时间将代码补上。