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 做相关的清除处理,使得此物理内存页成为空闲;另外还需把表示虚地址与物理地址对应关系的二级页表项清除

相关推荐
chenziang135 分钟前
leetcode hot100 环形链表2
算法·leetcode·链表
Captain823Jack2 小时前
nlp新词发现——浅析 TF·IDF
人工智能·python·深度学习·神经网络·算法·自然语言处理
Captain823Jack3 小时前
w04_nlp大模型训练·中文分词
人工智能·python·深度学习·神经网络·算法·自然语言处理·中文分词
是小胡嘛3 小时前
数据结构之旅:红黑树如何驱动 Set 和 Map
数据结构·算法
m0_748255023 小时前
前端常用算法集合
前端·算法
呆呆的猫4 小时前
【LeetCode】227、基本计算器 II
算法·leetcode·职场和发展
Tisfy4 小时前
LeetCode 1705.吃苹果的最大数目:贪心(优先队列) - 清晰题解
算法·leetcode·优先队列·贪心·
余额不足121384 小时前
C语言基础十六:枚举、c语言中文件的读写操作
linux·c语言·算法
火星机器人life6 小时前
基于ceres优化的3d激光雷达开源算法
算法·3d
虽千万人 吾往矣6 小时前
golang LeetCode 热题 100(动态规划)-更新中
算法·leetcode·动态规划