IA-32e架构下的内核初始化内存管理

简介: 初级内存管理单元关于内存的分页以往的物理页是按照4KB进行分配和管理的, 而在Linux之后流行的就是2MB大小的物理页的分配和管理, 整个物理内存管理单元也是2MB物理页管理的先获取基本的物理地址空间信息在bootloader程序中, 已经调用了BIOS的int 15h中断将物理内存...

初级内存管理单元

关于内存的分页

  • 以往的物理页是按照4KB进行分配和管理的, 而在Linux之后流行的就是2MB大小的物理页的分配和管理, 整个物理内存管理单元也是2MB物理页管理的

先获取基本的物理地址空间信息

  • 在bootloader程序中, 已经调用了BIOS的int 15h中断将物理内存地址的结构体放置到了1MB之下的物理地址0x7e00处, 我们需要将其提取出来
  • 每一条物理空间信息BIOS加载到内存时20B, 因此我们要获取该数据, 也需要定义一个结构体也占用20B的物理内存大小, 获取0x7e00地址上的数据, 但是在IA-32e模式下, 我们能够使用的是线性地址, 不能直接访问物理地址, 访问物理地址需要通过我们已经在head.S程序中定义好的页表进行页的映射, 在head.S中我们只进行了10MB的映射, 这对于我们目前来说已经足够了, 不过我们还是要知道物理地址0对应的线性地址时多少, 这样我们才能进行编码
  • 物理地址空间的大小为32个, 我们一开始先打印出这些信息, 输出物理内存哪些是可用的(type == 1), 如果多了脏数据(type > 4)证明这个地方的数据经不明数据污染了, 也就是说有数据将BIOS写到0x7e00地址上的数据覆盖了, 那我们就不要在读取了, 因为已经是错误的了, 没有意义了, 打印出来我们总共可用的内存大小

在分配可用物理页之前先获取可用物理页的页数

  • 在这个部分, 我们需要对复制BIOS的全部物理地址空间信息到一个memory_management_struct中, 这个结构体就是我们内存管理的核心, 它保存着所有的内存页的信息, 包括不可用的
  • 接下来我们计算出可用的物理内存页数, 获取一个可用的物理内存段之后, 我们对其起始地址尽心2MB的物理页的对齐, 返回的就是对齐后的物理地址, 接着计算出这个物理内存段的结束地址end, (end - start) >> page_2m_shift 计算出在这个物理段中有几个物理页, 也就一个分隔游戏, start就是对齐之后的物理地址, 在操作系统中一般有两个可用的物理地址段, 即为A和B, 他们一般不在一起, 第一个就是从我们的物理地址0开始的物理内存段, 显然我们的bootloader和内核代码都在这里, 这里肯定是可用的物理内存, 其实地址就是0, 对齐后的地址也是0, 因为2MB对齐就是将我们所有的内存分成一个一个的2MB, 但是另外一个可用的物理地址段它的start地址就不一定就是在一个矩形的2MB的起始位置了, 也就是说地址不对齐了, 这个时候我们就需要进行物理地址的对齐, 一般来说经过运算后, 我们原来的物理地址start的物理地址会增加一点到一个2MB的起始地址, 虽然这样会浪费一小段可用的物理地址空间, 但是我们完成了2MB的分隔, 更加方便我们的管理

分配可用物理内存页

需要用到的逻辑上的结构体
  • struct page --> 代表的就是我们说的2MB的物理页, 但是它本身不是2MB, 而是他管理的物理内存时2MB的, 这里所谓的管理就是通过属性保存地址, phyaddr就是管理的物理页的物理起始地址
  • struct zone --> 区域空间结构体, 它与page联系紧密, 它标志一个可用物理地址段, 就是我们在上面讲到了两个可用的物理地址段, 他代表着一个段, 怎么代表的呢, 也是通过属性startaddr和endaddr, startaddr保存着一个可用物理内存段的起始地址, endaddr保存着一个可用物理内存段的结束地址, 我们已经知道另一个一个物理段是很大的, 有多个2MB的物理页, 因此这里的endaddr - startadd的值也大于2MB, 所以会有多个page结构体引用着一个zone, 用来在逻辑层面上模拟分配一个页
  • 上面已经提到过的memory_management_struct(在后面简称为mm), 他包含了从BIOS获取的物理地址信息, bitsmap(就是一个整数, 和ext3文件系统一样一样的)用来方便索引空闲的物理页page, 一个page结构体数组(在逻辑上属于zone), 一个zone结构体数组, 内核代码结束位置, 自己的结束位置,注意page和zone结构体分配在了内核代码之后, zone在page之后
开始分配可用物理内存页(类似与Python中的__new__()魔法方法的功能, 但是与Java中的new关键字的功能不同, 这里只是为page和zone结构体分配了内存, 这里到处了实质: 可用物理页的分配就是在为结构体创建内存空间, 但是不进行初始化)
初始化bitmap
  • mm.bits_size属性赋值为我们之前计算出来的可用物理内存页的个数, 这样才能确定bitmap的大小
  • 将bitmap的值置为0, 虽然在这个时候我们的内核代码已经在内存中了, 我们理应将对应的bitmap中的一个位置位, 但是我们现在的内存管理的数据结构体还不完善, 所以我们将这个往后推
初始化page struct结构体数组
  • mm.pages_size等都记录下来, page结构体采用的4K物理页的对齐方式, 反正这些元数据结构体会比较特殊
  • 分配内存空间, 将所有的值初始化为0
初始化zone 结构体数组
  • 分配内存空间, 将所有的值初始化为0
第二次初始化(此时数据结构体的内存大致已经分配好了, 就是属性需要进行赋值, 类似于Python中的__init__()方法)
  • 先为zone结构体进行属性的初始化, 从mm中的bios的物理地址空间信息中读取 type == 1的地址, 对齐, 赋值该zone的start, end和上面的一样计算, 这样一个物理段就初始化完毕了, 此时在这个物理段zone的基础上初始上page的属性(但是这里的zone和page, 并不是所有的属性都被初始化了, 有一些需要在函数page_init中进行初始化), 我们知道page都是属于zone的, 通过循环将zone所代表的物理段分成多个2MB大小的物理页, 当然是使用page结构体的phyaddr和length来表示了, 接着这样page指向该zone, 表示page的所属是谁
现在我们也为page和zone的属性都赋值了, 现在我们就要通过一个page_init函数来初始化内核代码所在的内存, 还记得上面提到了在初始化bitmap的时候, 我说过的要将这个事情往后推吗!
  • 在初始化内存的时候, page的属性refcount++, page指向的zone的freepages--, pageusing++, 并且置位bitmap表示已用

  • 内存管理需要的东西完成了, 下面就是通过一个函数接口来通过访问这里的内存管理机制分配到内存了

通过alloc_pages函数返回一个struct page数组内核层和应用层使用

  • 判断向内存中的哪个区域要物理页
  • 通过bitmap找到指定连续数量的未被使用的位, 通过该位计算得出这个page数组的首地址, 将连续的page数据返回, 同时标志bitmap对应的位已用
目录
相关文章
|
19天前
|
编译器 C语言 C++
【C语言】memset()函数(内存块初始化函数)
【C语言】memset()函数(内存块初始化函数)
23 0
|
2月前
|
存储 监控 安全
360 企业安全浏览器基于阿里云数据库 SelectDB 版内核 Apache Doris 的数据架构升级实践
为了提供更好的日志数据服务,360 企业安全浏览器设计了统一运维管理平台,并引入 Apache Doris 替代了 Elasticsearch,实现日志检索与报表分析架构的统一,同时依赖 Doris 优异性能,聚合分析效率呈数量级提升、存储成本下降 60%....为日志数据的可视化和价值发挥提供了坚实的基础。
360 企业安全浏览器基于阿里云数据库 SelectDB 版内核 Apache Doris 的数据架构升级实践
|
26天前
|
Shell Linux C语言
【Shell 命令集合 磁盘维护 】Linux 创建一个初始化内存盘 mkinitrd命令使用教程
【Shell 命令集合 磁盘维护 】Linux 创建一个初始化内存盘 mkinitrd命令使用教程
33 0
|
5月前
|
存储 Linux Docker
跨cpu架构部署容器技术点:怎样修改Linux 的内核版本
在使用Docker 进行跨平台部署之后,我们还可以尝试进行跨架构部署。 从X86 架构上移植到 aarch64 上。
198 0
|
1月前
|
缓存 开发者
嵌入式微处理器的系统架构中微处理器的内核架构
嵌入式微处理器的系统架构中微处理器的内核架构
53 0
|
2月前
|
IDE Linux 开发工具
DP读书:鲲鹏处理器 架构与编程(十三)操作系统内核与云基础软件
DP读书:鲲鹏处理器 架构与编程(十三)操作系统内核与云基础软件
66 1
|
2月前
|
存储 缓存 数据处理
DP读书:鲲鹏处理器 架构与编程(八)3.1鲲鹏处理器片上系统与Taishan处理器内核架构
DP读书:鲲鹏处理器 架构与编程(八)3.1鲲鹏处理器片上系统与Taishan处理器内核架构
129 0
|
2月前
|
存储 缓存 并行计算
DP读书:鲲鹏处理器 架构与编程(四)内存顺序模型与内存屏障
DP读书:鲲鹏处理器 架构与编程(四)内存顺序模型与内存屏障
35 1
|
3月前
|
NoSQL Java 程序员
阿里开发人员献礼“Java架构成长笔记”,深入内核,拒绝蒙圈
提起阿里,行外人联想到的关键词无非是“交易”、“淘宝”、“支付宝”,但对于程序员来说,阿里庞大的技术体系才是最吸引人的。实际上阿里作为国内一线互联网公司的头把交椅,内部的技术体系和发展都是备受关注的,对于程序员来说,能够进到阿里工作,就是对自己的技术水平进行一个提升和学习。
阿里开发人员献礼“Java架构成长笔记”,深入内核,拒绝蒙圈
|
3月前
|
安全 Android开发
内存标记扩展:通过架构增强内存安全性
内存标记扩展:通过架构增强内存安全性
40 0