DragonOS/docs/kernel/memory_management/allocate-memory.md
LoGin 40fe15e095
新的内存管理模块 (#303)
  实现了具有优秀架构设计的新的内存管理模块,对内核空间和用户空间的内存映射、分配、释放、管理等操作进行了封装,使得内核开发者可以更加方便地进行内存管理。

  内存管理模块主要由以下类型的组件组成:

- **硬件抽象层(MemoryManagementArch)** - 提供对具体处理器架构的抽象,使得内存管理模块可以在不同的处理器架构上运行
- **页面映射器(PageMapper)**- 提供对虚拟地址和物理地址的映射,以及页表的创建、填写、销毁、权限管理等操作。分为两种类型:内核页表映射器(KernelMapper)和用户页表映射器(位于具体的用户地址空间结构中)
- **页面刷新器(PageFlusher)** - 提供对页表的刷新操作(整表刷新、单页刷新、跨核心刷新)
- **页帧分配器(FrameAllocator)** - 提供对页帧的分配、释放、管理等操作。具体来说,包括BumpAllocator、BuddyAllocator
- **小对象分配器** - 提供对小内存对象的分配、释放、管理等操作。指的是内核里面的SlabAllocator (SlabAllocator的实现目前还没有完成)
- **MMIO空间管理器** - 提供对MMIO地址空间的分配、管理操作。(目前这个模块待进一步重构)
- **用户地址空间管理机制** - 提供对用户地址空间的管理。
    - VMA机制 - 提供对用户地址空间的管理,包括VMA的创建、销毁、权限管理等操作
    - 用户映射管理 - 与VMA机制共同作用,管理用户地址空间的映射
- **系统调用层** - 提供对用户空间的内存管理系统调用,包括mmap、munmap、mprotect、mremap等
- **C接口兼容层** - 提供对原有的C代码的接口,是的C代码能够正常运行。


除上面的新增内容以外,其它的更改内容:
- 新增二进制加载器,以及elf的解析器
- 解决由于local_irq_save、local_irq_restore函数的汇编不规范导致影响栈行为的bug。
- 解决local_irq_save未关中断的错误。
- 修复sys_gettimeofday对timezone参数的处理的bug

---------

Co-authored-by: kong <kongweichao@dragonos.org>
2023-07-22 16:27:02 +08:00

30 lines
2.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 内存分配指南
&emsp;&emsp;本文将讲述如何在内核中进行内存分配。在开始之前请您先了解一个基本点DragonOS的内核使用4KB的页来管理内存并且具有伙伴分配器和slab分配器。并且对用户空间、内核空间均具有特定的管理机制。
## 1. 安全的分配内存
&emsp;&emsp;在默认情况下KernelAllocator被绑定为全局内存分配器它会根据请求分配的内存大小自动选择使用slab还是伙伴分配器。因此在内核中使用Rust原生的
内存分配函数,或者是创建一个`Box`对象等等,都是安全的。
## 2. 手动管理页帧
:::{warning}
**请格外小心!** 手动管理页帧脱离了Rust的内存安全机制因此可能会造成内存泄漏或者是内存错误。
:::
&emsp;&emsp;在某些情况下,我们需要手动分配页帧。例如,我们需要在内核中创建一个新的页表,或者是在内核中创建一个新的地址空间。这时候,我们需要手动分配页帧。使用`LockedFrameAllocator``allocate()`函数能够分配在物理地址上连续的页帧。请注意由于底层使用的是buddy分配器因此页帧数目必须是2的n次幂且最大大小不超过1GB。
&emsp;&emsp;当需要释放页帧的时候,使用`LockedFrameAllocator``deallocate()`函数,或者是`deallocate_page_frames()`函数,能够释放在物理地址上连续的页帧。
&emsp;&emsp;当您需要映射页帧的时候,可使用`KernelMapper::lock()`函数获得一个内核映射器对象然后进行映射。由于KernelMapper是对PageMapper的封装因此您在获取KernelMapper之后可以使用PageMapper相关接口对内核空间的映射进行管理。
:::{warning}
**千万不要** 使用KernelMapper去映射用户地址空间的内存这会使得这部分内存脱离用户地址空间的管理从而导致内存错误。
:::
## 3. 为用户程序分配内存
&emsp;&emsp;在内核中,您可以使用用户地址空间结构体(`AddressSpace`)的`mmap()`,`map_anonymous()`等函数为用户程序分配内存。这些函数会自动将用户程序的内存映射到用户地址空间中并且会自动创建VMA结构体。您可以使用`AddressSpace``munmap()`函数将用户程序的内存从用户地址空间中解除映射并且销毁VMA结构体。调整权限等操作可以使用`AddressSpace``mprotect()`函数。