Magenta - 内存管理概述

内存管理是个比较大的话题,本文只做个简单的介绍。建议先Magenta自带的文档memory,会对内存管理有个直观的认识。


涉及到的对象


Virtual memory address space(Vmas)

vmas表示处理器层面的地址空间,和具体的cpu的arch有关。一般分为2大类:kernel space和process space。在Magneta下输入命令“k vmm aspaces”会枚举出当前所有的vmas,缩减后的结果如下:

 as 0xffffffff8024db20 [0xffffff8000000000 0xffffffffffffffff] sz 0x8000000000 fl 0x1 ref 72 'kernel'
 as 0xffffff8001690060 [0x1000000 0x7fffffffefff] sz 0x7ffffefff000 fl 0 ref 31 'proc:1263'
 as 0xffffff8001691498 [0x1000000 0x7fffffffefff] sz 0x7ffffefff000 fl 0 ref 66 'proc:1283'
 as 0xffffff80016a89c8 [0x1000000 0x7fffffffefff] sz 0x7ffffefff000 fl 0 ref 38 'proc:1539'
 as 0xffffff80016aee28 [0x1000000 0x7fffffffefff] sz 0x7ffffefff000 fl 0 ref 108 'proc:1611'
 as 0xffffff80016b9928 [0x1000000 0x7fffffffefff] sz 0x7ffffefff000 fl 0 ref 45 'proc:1762'

第一行表示的是kernel space,其他是各个进程的process space。可见kernel的地址范围是

0xffffff8000000000 ~ 0xffffffffffffffff

而process的地址范围如下:

0x1000000 ~ 0x7fffffffefff

这些地址的定义请参见 kernel/arch/x86/rules.mk 中的宏:

KERNEL_ASPACE_BASE ?= 0xffffff8000000000UL # -512GB
KERNEL_ASPACE_SIZE ?= 0x0000008000000000UL
USER_ASPACE_BASE   ?= 0x0000000001000000UL # 16MB
USER_ASPACE_SIZE   ?= 0x00007ffffefff000UL

Magenta使用结构体 “class VmAspace” 表示vmas,其成员”ArchVmAspace arch_aspace_“表示具体arch下的地址访问,目前可以使用如下2者之一。

using ArchVmAspace = X86ArchVmAspace;
using ArchVmAspace = ArmArchVmAspace;

Virtual memory address region(Vmar)

请参考vm_address_region

vmar用于表示一段连续的虚拟地址空间,以数据结构class VmAddressRegion表示。kernel space和process space初始只有一整块vmar,以class VmAspace 的成员 mxtl::RefPtr< VmAddressRegion> root_vmar_表示。后续可以在root_vmar_上被分配子块或者回收;在子块上也可以做分配和回收。所以vmar是有层次结构的,class VmAddressRegion的成员ChildList subregions_ 和 VmAddressRegion* parent_分别用于表示其子块和父块。

命令“k vmm aspaces”的vmar部分缩减输出如下:

#kernel的vmar
 vmar 0xffffffff8024d9a0 [0xffffff8000000000 0xffffffffffffffff] sz 0x8000000000 ref 1 'root'
   vmar 0xffffff8001636e00 [0xffffff9000004000 0xffffff9000e04fff] sz 0xe01000 ref 2 'arena:handles'

#以下表示3个process的vmar
 vmar 0xffffff8001690230 [0x1000000 0x7fffffffefff] sz 0x7ffffefff000 ref 2 'root'
   vmar 0xffffff8001697f18 [0x1397428fe000 0x139742906fff] sz 0x9000 ref 1 'useralloc'
   vmar 0xffffff800169aa58 [0x2f554d7d7000 0x2f554d817fff] sz 0x41000 ref 1 'useralloc'

 vmar 0xffffff8001691668 [0x1000000 0x7fffffffefff] sz 0x7ffffefff000 ref 2 'root'
   vmar 0xffffff800169d7a0 [0x71f0b8ea000 0x71f0b8ecfff] sz 0x3000 ref 1 'useralloc'
   vmar 0xffffff8001694a18 [0x9ea73f6a000 0x9ea73faafff] sz 0x41000 ref 1 'useralloc'
   vmar 0xffffff800169c148 [0x1869902a7000 0x1869902a9fff] sz 0x3000 ref 1 'useralloc'

 vmar 0xffffff800169f3e0 [0x1000000 0x7fffffffefff] sz 0x7ffffefff000 ref 2 'root'
   vmar 0xffffff80016b4bc8 [0x786f8c4d000 0x786f8c50fff] sz 0x4000 ref 1 'useralloc'
   vmar 0xffffff80016ab6e8 [0x11f837604000 0x11f83760ffff] sz 0xc000 ref 1 'useralloc'
   vmar 0xffffff80016abff0 [0x24ae539b6000 0x24ae539cefff] sz 0x19000 ref 1 'useralloc'

root_vmar_的范围一般设置为VmAspace的地址空间范围大小。所以kernel的vmar范围如下:

[0xffffff8000000000 0xffffffffffffffff]

而process的范围如下:

 [0x1000000 0x7fffffffefff]

Virtual memory mapping(Vmm)

请参考vmar_map。mapping就是将vmo映射到vmar。


Virtual memory object(Vmo)

请参考vm_object

vmo也表示一段连续的虚拟地址空间,但此空间指向物理页或memory-map的device区域。从某种意义上讲,vmo的行为更像文件,可以读取,可以被mapping。

Magenta以数据结构class VmObject表示vmo,而以其子类class VmObjectPaged表示指向物理页的vmo。那么paged vmo是什么时候分配物理页的呢?

在没有被mapping,直接调用mx_vmo_read/write时,如果还未分配物理页,在读的情况下,直接读取zero oage;在写的情况下,则分配物理页给vmo,后续可以写至此物理页。如果此vmo是从其他vmo通过clone而来,且父vmo对应于offset的物理页已分配,如是读,则从此物理页读取;如是写,则行为类似于COW,即先分配一个物理页,将父vmo的页copy此新page,然后作为vmo的物理页。 物理页由class VmObjectPaged的成员 VmPageList page_list_管理。

调用mx_vmar_map显式的映射vmo,将vmo映射于一段虚拟地址空间。后期在访问此虚拟空间时,会产生缺页中断,分配物理页并建立映射。调用流程如下:

x86_exception_handler
->x86_pfe_handler
  ->vmm_page_fault_handler
     ->VmAspace::PageFault
       ->VmAddressRegion::PageFault
         -> 如果此段虚拟地址是VmMapping,则VmMapping::PageFault

当是读缺页时,依然是将zero page映射至vmo的虚拟空间,但此时映射为read only;后续如果要写此段虚拟空间,则依然会产生异常,从而可以分配新物理页并重新映射。

那么如果没有mapping,vmo是否会占虚拟地址空间? 此时vmo只占有物理页,读写物理页时,先将物理页的物理地址转变为kernel虚地址再读写。所以占有的是物理页的虚拟地址空间。

vmo的koid为0时,表示vmo没有被user引用,只有kernel指向此vmo。从代码看,在vmo创建时,koid默认值是0;后期在创建VmObjectDispatcher时,将VmObjectDispatcher的koid赋值给vmo的koid。


四者的关系

搬用memory中的例子,四者的topology如下:

$ vmaps 2470
/A ________01000000-00007ffffffff000    128.0T:sz                    'proc:2470'
/R ________01000000-00007ffffffff000    128.0T:sz                    'root'
R  00000187bc867000-00000187bc881000      104k:sz                    'useralloc'
   M 00000187bc867000-00000187bc87d000 r-x   88k:sz   0B:res  2535:vmo 'libmxio.so'
   M 00000187bc87e000-00000187bc87f000 r--    4k:sz   4k:res  2537:vmo 'libmxio.so'
   M 00000187bc87f000-00000187bc881000 rw-    8k:sz   8k:res  2537:vmo 'libmxio.so'
  ...
M  0000246812b91000-0000246812d91000 rw-    2M:sz  76k:res  2542:vmo 'mmap-anonymous'
...
R  0000358923d92000-0000358923dd3000      260k:sz                    'useralloc'
   M 0000358923d93000-0000358923dd3000 rw-  256k:sz  16k:res  2538:vmo ''
   ...

 "/A" -- Process address space
  "/R" -- Root VMAR
  "R"  -- VMAR (R for Region)
  "M"  -- Mapping
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值