图片无法显示,请右键点击新窗口打开图片

BiscuitOS 内存管理之分页大专题订阅入口

图片无法显示,请右键点击新窗口打开图片

在 Linux 用户空间,虚拟内存可以通过两种映射方式与物理内存建立映射关系,第一种是 File-Mapping 文件映射,其可以将文件内容映射到用户空间,虚拟内存和磁盘文件中间通过 Page CACHE 进行数据中转,因此可以像普通虚拟内存一样访问文件; 另外一种是 Anonymous-Mapping 匿名映射, 用于将用户空间虚拟内存映射到物理内存上,以满足进程对内存的需求,例如堆(Heap)内存、堆栈(Stack)内存、以及 MMAP 内存等。两种映射方式的不同点在于是否有后端文件,匿名内存 可以通过 malloc/brk/mmap 进行分配

图片无法显示,请右键点击新窗口打开图片

另外 Linux 还支持共享内存,其可以通过 mmap 函数进行分配,分配时采用分配标志: MAP_SHARED 与 MAP_ANONYMOUS. 而匿名内存同样可以使用 mmap 进行分配,其分配标志是: MAP_PRIVATE 与 MAP_ANONYMOUS。虽然两者都采用了 MAP_ANONYMOUS, 但是两者的处理逻辑是不同的,虽然共享内存没有明确指明后端文件,当内核会为每个共享文件关联一个 tmpfs 文件系统的文件,而匿名内存 Linux 是不会关联任何文件的,因此从这个角度来看,采用 MAP_PRIVATE 与 MAP_ANONYMOUS 的内存才能称为匿名内存.

图片无法显示,请右键点击新窗口打开图片

分配匿名内存的函数很多,其中最常用的是 mmap,由于其提供了多种配置参数,可以分配更灵活的匿名内存。当使用 mmap 系统调用分配匿名内存时,各参数的含义如下:

  • ARG0: MAP_VADDR 可以知道匿名内存的虚拟地址,该值为 NULL 是代表分配一个随机的虚拟地址,当该值为指定值时代表从指定的地址分配虚拟内存,该地址可能已经被分配出去,使用时调用者需要确保虚拟地址被覆盖.
  • ARG1: MAP_SIZE 指明了需要分配匿名内存的大小,长度为 PAGE_SIZE 的倍数,不能为 0.
  • ARG2: 指明了匿名内存的访问权限,其值可以是这些标志的合集: PROT_READ(可读)、PROT_WRITE(可写)、PROT_EXEC(可执行) 和 PROT_NONE(不可访问)
  • ARG3: 指明映射类型,该字段必须包含是 MAP_PRIVATE 和 MAP_ANONYMOUS 标志,否则无法分配到匿名内存.
  • ARG4: 映射文件描述符,对于匿名内存由于其没有后端文件,因此这里必须为 -1.
  • ARG5: 指明映射的物理区域,由于匿名内存映射的随机物理内存,因此该字段必须为 0.

图片无法显示,请右键点击新窗口打开图片

在匿名内存架构里,VMA 通过页表正向映射到匿名页上,并且每个 VMA 维护一个 STRUCT anon_vma 的数据结构(简称为 AV),该数据结构里存在一颗红黑树,该红黑树的节点为 STRUCT anon_vma_chain(简称为 AVC), 每个 AVC 都指向另外一个 VMA,那么每个 AVC 可以表示映射到该匿名页的 VMA,最后将匿名页的 mapping 指向 AV。有了上面的关系之后,如>果获得一个匿名页之后,想通过逆向映射知道哪些 VMA 映射了该匿名页,那么可以通过匿名页的 mapping 获得 AV,然后遍历 AV 对应的红黑树获得每一个 AVC,在通过 AVC 获得 VMA 即可.

图片无法显示,请右键点击新窗口打开图片

图片无法显示,请右键点击新窗口打开图片

BiscuitOS 内存管理之分页大专题订阅入口

图片无法显示,请右键点击新窗口打开图片