内存热插拔

1、 内存热插拔
— linux/Documentation/memeory-hotplug.txt
1.1、 内存热插拔的目的
内存热插拔允许使用者去增加或减少内存的大小。这样做通常出于两种目的:

(A) For changing the amount of memory. This is to allow a feature like capacity on demand.
调整内存容量,这是为了允许按照需求容量进行划分;
(B) For installing/removing DIMMs or NUMA-nodes physically. This is to exchange DIMMs/NUMA-nodes, reduce power consumption, etc.
物理上安装或卸载 DIMMs 或NUMA-nodes ,交换DIMMs/NUMA-nodes,减少功耗;
(A) is required by highly virtualized environments and (B) is required by hardware which supports memory power management.
(A) 是高度虚拟化环境所必需的,(B) 是支持内存电源管理的硬件所必需的。
1.2、 内存热插拔的阶段
内存热插拔分为两个阶段
1) 物理内存热插拔阶段
第一阶段是为热插拔内存通信硬件/固件和创建/擦除环境。基本上,对目的(B)来说这个阶段时必须的;当内存被热插入时,内核会识别新内存,创建新的内存管理表,并为新内存的操作创建 sysfs 文件。如果固件支持新内存连接到操作系统的通知,则此阶段会自动触发。ACPI可以通知系统中有新的内存加入事件。如果不支持,系统管理员可以使用“probe”操作。

  1. 逻辑内存热插拔阶段
    逻辑内存热插拔阶段是将内存状态更改为对用户可用/不可用。
    此阶段更改了用户视角中的内存量。当内存范围可用时,内核会将其中的所有内存作为空闲页面。
    在这个文档中,逻辑内存热插拔阶段被描述为上线、下线。
    通过系统管理员对sysfs文件进行写操作,可以触发逻辑内存热插拔阶段。对这种热添加情况,在物理热插拔完成以后,逻辑热插拔阶段必须被执行通过手动操作。但是,如果你写了一个为内存热插拔的udev’s hotplug scripts脚本的话,这些阶段可以被透明的执行。
    1.3、 内核配置支持该功能
    内存模型
    Memory Management options —>
    Memory model (Sparse Memory)
    允许内存热添加
    Memory Management options —>
    [] Allow for memory hot-add
    若需要在插入新内存,系统自动将其上线则配置:
    [
    ] Online the newly added memory blocks by default

为了能移除内存,下面的选项是必须的
Memory Management options —>
[] Allow for memory hot remove
[
] Allow for memory compaction
2、 内存热插拔怎样通过/proc简单操作配置
All memory blocks have their device information in sysfs. Each memory block
is described under /sys/devices/system/memory as:
/sys/devices/system/memory/memoryXXX
(XXX is the memory block id.)
以某aarch64平台为例,内核配置为:
在这里插入图片描述
整体内存大小为8GB,OS划分为2GB,地址从0x0~0x80000000;
在这里插入图片描述
系统内存:
在这里插入图片描述
【添加】
将2GB为起始的一个section添加到OS中;
[debug@dvrdvs memory] # echo 0x80000000 > /sys/devices/system/memory/probe
在这里插入图片描述
[debug @dvrdvs memory32] # ls
online phys_index state uevent
phys_device removable subsystem valid_zones
[debug @dvrdvs memory32] # cat online
0
[debug @dvrdvs memory32] # cat …/memory31/online
1
[debug @dvrdvs memory32] # cat state
offline
[debug @dvrdvs memory32] # echo 1 > online
在这里插入图片描述
[debug @dvrdvs memory32] # cat valid_zones
Normal

2106636 – 2041100 KB = 65536 KB = 64MB
在/proc/iomem中可以看到刚刚添加的内存信息:
80000000-83ffffff : System RAM
【移除】
逻辑内存移除
内存下线比内存上线更加的复杂。因为内存下线必须使整个内存段都未使用,如果内存段中包含有仍未释放的内存段,内存下线操作就可能失败。

[debug @dvrdvs] # echo offline > /sys/devices/system/memory/memory32/state
顺利时系统会将该部分内存下线:[ 507.843281] Offlined Pages 16384
在这里插入图片描述
如果下线操作失败,内核将会返回一些错误值(像:-EBUSY)。即使一个内存段不属于ZONE_MOVABLE,你也可以尝试去下线它。处于ZONE_MOVABLE的内存段被认为是能很容易下线的。但是如果这样的内存段处于繁忙的状态下,对它们进行下线,系统会返回-EBUSY。即使一个内存段由于-EBUSY而不能下线,你可以重试,并且有可能会成功与有可能失败。
物理内存的移除
Need more implementation yet…

  • Notification completion of remove works by OS to firmware.
  • Guard from remove if not yet.
    但系统中仍然可以看到memory32节点以及上面添加到iomem中的内存段信息。
    一个memoryXXX节点有哪些属性呢?
    在这里插入图片描述
    经测试,对state的设置online和online_kernel属性相同,都是将页内存添加到了ZONE_Normal区。在配置为online_movable时页内存添加到了ZONE_Movable区,这一点可以从/proc/zoneinfo中看到。
    ZONE_MOVABLE是无法被slab、get_free_pages、vmalloc分配,只能被alloc_pages接口并且带有GFP_MOVABLE参数属性时优先从该区域分配,理论上应用的堆栈是可以分配到该ZONE内存的。如此可能会出现剩余内存的ZONE_MOVABLE内存较大,而调用的slab、get_free_pages、vmalloc分配内存失败的情况。

3、 内存热插拔的实现基础
内存热插拔特性是基于稀疏内存模型(Sparse Memory Model)实现;Linux内核支持3种内存模型,分别是flat memory model、Discontiguous memory model和sparse memory model。memory model是从cpu的角度看,其物理内存的分布状况。三种内存模型对应的特性如下:
1、 平坦内存(Flat Memory):内存的物理地址空间是连续的,没有空洞;
在这里插入图片描述

2、 不连续内存(Discontiguous Memory):内存的物理地址空间存在空洞;
在这里插入图片描述

3、 稀疏内存(Sparse Memory):存在空洞且支持内存的热插拔;
在这里插入图片描述

从图中可见整个物理内存空间被分成了n个section。在稀疏内存模型中物理内存以section为单位进行了划分。

3.1、section
在SPARSEMEM中,被管理的物理内存由一个个任意大小的section(struct mem_section表示)构成,所以整个物理内存可被视为一个mem_section数组。每一个mem_section包含了一个间接指向struct page数组的指针。
在这里插入图片描述

ARM64平台默认都配置为稀疏内存模型,在不同平台中section的大小各不相同。
下面为内存probe上线以及添加到伙伴系统的大致流程图,
在这里插入图片描述

将可移动设备连入系统时,系统的后台中会依次发生如下事件: l 内核检测到新硬件插入,然后分别通知hotplug和udev。前者用来装入相应的内核模块(如usb-storage),而后者用来在/dev中创建相应的设备节点(如/dev/sda1)。 l udev创建了相应的设备节点之后,会将这一消息通知hal的守护程序(hald)。当然udev还得保证新创建的设备节点可以被普通用户访问。 l hotplug装入了相应的内核模块之后,会把这一消息通知给hald。 l hald在受到hotplug和udev发出的消息之后,认为新硬件已经正式被系统认可了。此时它会通过一系列精心编写的规则文件(就是传说中的xxx-policy.fdi),把发现新硬件的消息通过dbus发送出去,同时还会调用update-fstab或fstab-sync来更新/etc/fstab,为相应的设备节点创建适合的挂载点。 l 卷管理器会监听dbus中发现新硬件的消息。根据所插入的硬件(区分U盘和数码相机等)不同,卷管理器会先将相应的设备节点挂载到hald创建的挂载点上,然后再打开不同的应用程序。 当然,如果是在CDROM中插入光盘,过程可能比较简单。因为CDROM本身就是一个固定的硬件,无需hotplug和udev的协助: l hald会自己监视CDROM,并且将光盘托架开合的消息通过dbus发出去。 l 卷管理器负责检查CDROM中的盘片内容,进行挂载,并调用合适的应用程序。 要注意,hald的工作是从上游得到硬件就绪的消息,然后将这个消息转发到dbus中。尽管它会调用程序来更新fstab,但实际上它自己并不执行挂载的工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值