ucore 清华实验物理内存篇

  • 理解基于段页式内存地址的转换机制

  • 理解页表的建立和使用方法

  • 理解物理内存的管理方法

手动实现简易的物理内存管理系统

基本的函数

default_pmm_manager 的结构体变量,类型为 struct pmm_manager。这个结构体变量包含了默认的物理内存管理器的信息和功能。

具体来说,它的意思如下:

  • .name = "default_pmm_manager":给物理内存管理器取了一个名字,即 "defaultpmmmanager"。

  • .init = default_init:指定了初始化函数,即 default_init 函数,用于初始化物理内存管理器。

  • .init_memmap = default_init_memmap:指定了初始化内存映射的函数,即 default_init_memmap 函数,用于初始化空闲物理页的映射。

  • .alloc_pages = default_alloc_pages:指定了分配内存页的函数,即 default_alloc_pages 函数,用于从物理内存中分配一页或多页的内存。

  • .free_pages = default_free_pages:指定了释放内存页的函数,即 default_free_pages 函数,用于将不再使用的内存页释放回物理内存。

  • .nr_free_pages = default_nr_free_pages:指定了获取空闲内存页数量的函数,即 default_nr_free_pages 函数,用于获取当前物理内存中的空闲页数量。

  • .check = default_check:指定了检查函数,即 default_check 函数,用于检查物理内存管理器的正确性。

  1. 首次适应分配算法 实现 first-fit 连续物理内存分配算法

首先

假设我们有一段连续的内存,通过 default_init_memmap() 函数初始化为以下状态:

```Plain Text plaintextCopy code +-------------------+ | Free (nrfree) | +-------------------+ ^ ^ | | freelist End

复制代码
### `static struct Page * default_alloc_pages(size_t n)` 此函数为分配空闲页

让我们通过图示来解释代码的执行过程。

假设我们有一个空闲页链表,如下所示:

+-------+ +-------+ +-------+ +-------+

| Page1 | | Page2 | | Page3 | | Page4 |

+-------+ +-------+ +-------+ +-------+

4页 3页 5页 2页

复制代码
每个空闲页都有一个属性 `property` 记录了它的大小。

现在,假设我们调用 `default_alloc_pages(4)`,希望分配一个大小为 4 页的空闲块。

代码执行过程如下:

2. **初始化**:我们初始化一个指针 `le` 指向空闲页链表的头部。

3. **遍历空闲页链表**:我们开始从头部遍历空闲页链表,寻找一个大小大于等于 4 页的空闲块。

4. **找到合适的空闲块**:假设在遍历过程中,我们找到了 `Page3`,它的大小为 5 页。

+-------+ +-------+ +-------+ |

Page1 | | Page2 | | Page4 |

+-------+ +-------+ +-------+

4页 3页 2页

复制代码
5. **分配空闲块**:我们将 `Page3` 分配出去,并从空闲页链表中删除。

+-------+ +-------+ +-------+ |

Page1 | | Page2 | | Page4 |

+-------+ +-------+ +-------+

4页 3页 2页

复制代码
6. **更新空闲页链表**:由于 `Page3` 的大小超过了需要的 4 页,因此我们需要将剩余的部分重新加入到空闲页链表中。

+-------+ +-------+ +-------+ +-------+ |

Page1 | | Page2 | | Page3 | | Page4 |

+-------+ +-------+ +-------+ +-------+

4页 3页 1页 2页

复制代码
这样,我们就完成了一次内存分配的过程。整个过程中,代码按照从头部开始的顺序遍历空闲页链表,找到了第一个大小满足要求的空闲块,并进行了相应的分配操作。



### 即 `default_free_pages` 函数,用于将不再使用的内存页释放回物理内存。

给定内存中包含的页以及释放内存的情况,如下所示:

+-------+-------+-------+-------+-------+-------+ |

Page1 | Page2 | Page3 | Page4 | Page5 | Page6 |

+-------+-------+-------+-------+-------+-------+

复制代码
假设我们要释放从 `Page2` 开始的 3 页内存。

7. **初始状态**:在初始状态下,我们有六个页,每个页都是可用的。

+-------+-------+-------+-------+-------+-------+

| Page1 | Page2 | Page3 | Page4 | Page5 | Page6 |

+-------+-------+-------+-------+-------+-------+

复制代码
8. **释放内存页**:我们从 `Page2` 开始释放 3 页内存,并将它们标记为可用。

+-------+-------+-------+-------+-------+-------+ |

Page1 | Free | Free | Free | Page5 | Page6 |

+-------+-------+-------+-------+-------+-------+ ```

  1. 合并连续的空闲页:由于释放的内存页与相邻的空闲页相连,因此我们将它们合并为一个更大的空闲页。

即一整个free空闲页

default_nr_free_pages:指定了获取空闲内存页数量的函数

static size_t

defaultnrfree_pages(void) {

return nr_free;

}

实现寻找虚拟地址对应的页表项

页目录项(Page Directory Entry)和页表项(Page Table Entry)是 x86 架构下操作系统管理虚拟内存的重要数据结构。

页目录项(Page Directory Entry):

  • Present (P):表示页目录项是否存在,用于判断页表是否存在于内存中。

  • Read/Write (R/W):表示页表对应的页面是否可读写,用于设置页表权限。

  • User/Supervisor (U/S):表示页表对应的页面是否可供用户态程序访问,用于设置页表权限。

  • Accessed (A):表示该页表项是否被访问过,用于页面置换算法。

  • Dirty (D):表示该页表对应的页面是否被修改过,用于页面置换算法和页面写回判断。

  • Page Table Base Address (PTBA):存储页表的物理地址,指向页表的起始地址。

页表项(Page Table Entry):

  • Present (P):表示页表项是否存在,用于判断物理页面是否存在于内存中。

  • Read/Write (R/W):表示物理页面是否可读写,用于设置页面权限。

  • User/Supervisor (U/S):表示物理页面是否可供用户态程序访问,用于设置页面权限。

  • Accessed (A):表示该页表项对应的页面是否被访问过,用于页面置换算法。

  • Dirty (D):表示该页表对应的页面是否被修改过,用于页面置换算法和页面写回判断。

  • Page Base Address (PBA):存储物理页面的起始地址。

当ucore执行过程中访问内存出现页访问异常时,硬件会进行以下处理:

  1. 检查页目录项和页表项中的标志位,如Present、Read/Write、User/Supervisor等,确定访问权限。

  2. 如果页表项或页目录项不存在,会引发页错误异常(Page Fault Exception)。

  3. 操作系统会根据页错误异常的处理机制,将缺失的页面从磁盘加载到内存中,更新页表项,并重新执行引发异常的指令。

释放某虚地址所在的页并取消对应二级页表项的映射

当释放一个包含某虚地址的物理内存页时,需要让对应此物理内存页的管理数据结构 Page 做相关的清除处理,使得此物理内存页成为空闲;另外还需把表示虚地址与物理地址对应关系的二级页表项清除

相关推荐
漂流瓶jz16 分钟前
UVA-1613 K度图的着色 题解答案代码 算法竞赛入门经典第二版
算法·深度优先·图论·贪心·aoapc·算法竞赛入门经典·uva
Pniubi1 小时前
动态规划入门 ( - 力扣509斐波那契数)
算法·动态规划
吴长建先生重名了2 小时前
GitHub Actions部署报表系统踩坑记:幂等性与限
算法
贝壳6903 小时前
一个2026年2月才上传的库,凭什么敢碰2009年就有人写烂的题目
算法
贝壳6903 小时前
同一道三亿位选型题,三个AI给了我三个答案,我把它们拉进同一台机器复跑
算法
青少儿编程课堂5 小时前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会图形化考级:校园大富翁经营闯关解析
c++·python·算法·bfs·信息学竞赛
在所不辞兄6 小时前
为什么在新能源汽车电驱与热管理开发中,AI驱动的数字孪生和数据驱动仿真正在部分替代对物理台架与实车标定的依赖?
人工智能·深度学习·神经网络·算法·机器学习
I_belong_to_jesus16 小时前
C++关于分支预测的优化1
开发语言·c++·算法
Code_Solitude1 天前
C语言动态内存 + 柔性数组 + 数组名退化
c语言·算法·柔性数组