Redian新闻
>
如何增加 iOS APP 虚拟地址空间及内存上限?XNU 内核源码解读

如何增加 iOS APP 虚拟地址空间及内存上限?XNU 内核源码解读

科技

1. 引言

最近一段时间在做钉钉 iOS 内存专项治理,解决内存不足时的 jetsam 事件及 malloc 的异常崩溃。在进程创建时系统会为每个 app 设定内存最大使用上限,内核会维护一个内存阈值优先级列表,当设备内存不足时低优先级的 app 会首先被内核中止进程。在阅读 XNU 内核源码过程中我们发现提供系统了两种能力可以扩展 App 的虚拟地址空间(com.apple.developer.kernel.extended-virtual-addressing)和增加内存使用上限(com.apple.developer.kernel.increased-memory-limit)。

2. 扩展虚拟地址空间

每个 App 进程都有自己的虚拟地址空间,在 32 位系统时,虚拟地址空间为 4G,按一般理解 64 位系统虚拟内存地址不受限制的,但通过阅读 XNU 代码发现虚拟地址空间和设备有关联,不同的设备虚拟地址空间是不一样的。当 App 开启"com.apple.developer.kernel.extended-virtual-addressing"这个 entitlement 能力后,内核会增加 App 的虚拟地址空间,使用这个能力 App 可以获得更大的地址空间,解决业务需要申请大的虚拟地址分配导致的崩溃异常。苹果官方解释如下:

“A Boolean value that indicates whether the app may access an extended address space.

Use this entitlement if your app has specific needs that require a larger addressable space. For example, games that memory map assets to stream to the GPU may benefit from a larger address space”

2.1 方案

如何开启这个能力呢?需要在 App entitlement 文件里增加 “com.apple.developer.kernel.extended-virtual-addressing” 的配置,设置 value 的值为 True,同时需要更新证书。

2.2 数据验证

我们通过测试代码来验证下开启 “com.apple.developer.kernel.extended-virtual-addressing” 和未开启时的数据对比。由于是增加虚拟内存地址空间,我们尝试无限分配大内存但不 Dirty 数据试试,每次循环分配 1M 内存,直到无法分配内存地址,最后统计分配的内存数据大小。部分代码如下

测试数据如下:

从测试数据上惊奇发现未开启地址空间是 2G,开启后达到 54G,开启后内核会为 App 扩展足够使用的虚拟地址空间。

2.3 内核源码分析

通过分析 XNU 内核源码,我们发现如果开启 “com.apple.developer.kernel.extended-virtual-addressing” 能力后,内核会开启一种称之为 “jumbo” 模式。未开启 “jumbo” 模式时不同的设备虚拟地址空间是不一样的,虚拟地址空间和设备有关联,当开启后在 iOS14 以上设备虚拟地址空间会达到 64G。整体数据如下列表:

2.3.1 开启 jumbo 模式

App 进程创建时通过判断 Entitlement 是否开启 “com.apple.developer.kernel.extended-virtual-addressing” 配置能力来决定是否开启 “jumbo” 模式。代码如下

2.3.2 jumbo 模式申请地址空间

64 位通过 pmap_max_64bit_offset 这个接口来申请虚拟地址空间,如果开启“jumbo”模式,这个接口参数 option 的值是 ARM_PMAP_MAX_OFFSET_JUMBO,如果未开启 option 的值是 ARM_PMAP_MAX_OFFSET_DEVICE,通过代码发现 ARM_PMAP_MAX_OFFSET_DEVICE 选项在不同的设备的空间是不一样的。部分核心代码如下:

3. 增加内存上限

在进程创建时,系统会为 App 指定默认的内存上限,在 App 运行过程中分配的内存超过内核指定的内存上限时,内核会触发 jetsam 机制主动中止当前进程。在研究 XNU 内核代码过程中,发现系统提供了三种方式来增加 App 的内存使用上限。如果 App 申请了“com.apple.developer.kernel.increased-memory-limit” entitlement 配置能力后,内核会增加 App 的内存上限。当 App 分配的内存超过系统默认的内存上限后,App 仍然可以继续很好的运行。相对于未申请该能力的其他进程,拥有该能力的 App 有了更高内存使用优先级。苹果官网解释如下:

“A Boolean value that indicates whether core features of your app may perform better with a higher memory limit on supported devices.

Add this entitlement to your app to inform the system that some of your app’s core features may perform better by exceeding the default app memory limit on supported devices. If you use this entitlement, make sure your app still behaves correctly if additional memory isn’t available”。

3.1 方案

苹果提供了如下三种方式来主动增加 App 的内存上限。主动申请增加内存上限需要在 entitlement 里增加配置能力,三种方案各有不同的策略,而且有些方案是内核私有能力。三种方案对比如下:

我们在钉钉 App 里申请使用了“com.apple.developer.kernel.increased-memory-limit”配置能力。

如何开启这个能力呢?需要在 App entitlement 文件里增加“com.apple.developer.kernel.increased-memory-limit” 的配置,设置 value 的值为 True,同时需要更新证书。

3.2 数据验证

我们通过测试代码来验证下开启 “com.apple.developer.kernel.increased-memory-limit” 和未开启时的数据对比。由于增加 App 的内存使用上限,通过尝试申请 Dirty 内存来查看 app 被 kill 的内存上限,开启 timer,每 s 分配 20M 内存,部分代码如下:

通过测试发现,开启增加内存上限 entitlement 后,相比未开启内存分配的数据会略微增加。

3.3 内核源码分析

3.3.1 内存告警计算

进程 task 初始化时会解析启动的入参“max_task_pmem”,读取 app 最大的内存限制。App 内存最大限制及告警阈值和设备内存的大小有关联,当 App 使用内存超过最大内存限制的 80%时会发出 warning 初步告警。计算列表如下:

部分核心代码如下:

3.3.2 能力开启

App 进程创建时通过判断 Entitlement 是否开启 “com.apple.developer.kernel.increased-memory-limit” 配置能力,如果开启后通过 “memorystatus_act_on_entitled_task_limit” 方法来增加内存上限。核心代码如下:

3.3.3 设置最大内存

task 启动时会设置 task 的内存 limit,通过启动参数“entitled_max_task_pmem”来读取“memorystatus_entitled_max_task_footprint_mb”最大内存上限。然后通过“memorystatus_raise_memlimit” 方法来配置 App 最大内存。核心代码如下:

4. 总结

通过内核探索我们初步了解了系统在虚拟地址空间和内存分配上限的运行逻辑,申请两种能力后 App 可以申请更多的虚拟地址空间和内存上限。开启 “jumbo” 模式 可以解决一些大地址内存映射地址空间不足导致的异常及崩溃等问题,申请增加内存上限后 App 可以获得更多的内存分配优先权,App 运行会更加流畅。

5. 参考

  • https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_kernel_increased-memory-limit?language=objc
  • https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_kernel_extended-virtual-addressing?language=objc
  • https://github.com/apple/darwin-xnu



微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
至今没感染是“天选之子”?XBB会致二次感染吗?专家解答!郑州有医院推出千元“阳康”体检套餐?上海给一线医护发6000元津贴华为开发者贡献 Linux 内核补丁,将核心内核函数速度提升 715 倍什么情况下可采取紧急防控措施?XBB会造成大规模流行吗?解答来了佛州基韦斯特(Key West),小岛路景测试 | 你的样貌是什么风格?如何突破颜值上限?免费开源虚拟机 VirtualBox 7.0.4 发布,初步支持 Linux 6.1 内核硬核观察 #848 Linux 6.1 发布,拉开 Rust 进入 Linux 内核的大幕加州的老墨 – 6纽约/新泽西 泽西市渣男 DATING APP 加州湾区滨州NSR综述 | 如何增强可拉伸电子元件之间的界面结合强度?李铁,对得起我们吗?XXX,退钱!下波大疫情来袭?XBB毒株美国感染率登顶!很快席卷加拿大,逃脱免疫能力最强!图解各种改地址 | 吐血整理搬家后需要修改地址的清单和攻略平面专业越来越卷,时间有限如何增加「作品丰富度」?如何增效,实现破局?在 Mac 上运行 Linux 更进一步,Apple SoC CPUFreq 驱动即将并入 Linux 主线内核英华号周播报|震荡市中如何增强投资者信心?历史大底反转的条件已具备几个?赴华:“乙类乙管”后,中美航班会如何增加?Arch Linux 2023.01.01 版本 ISO 镜像发布:采用 Linux 内核 6.1俄罗斯与西方的石油之争:俄方将如何应对价格上限?“给我脱!”这家公司面试一进门就被要求脱下裙子、裤袜及内衣等衣物果然,由外及内的通稿来了,又强卖美国“神药”终于官宣!香港大陆通关时间及安排公布!已经开始抢名额!刚刚,蒙脱石散被抢光了?XBB.1.5成美国头号流行株!摩洛哥宣布“禁止来自中国的旅客入境,不论国籍”!广州:本轮疫情已达峰Linux 6.1 内核被批准为长期支持版本 | Linux 中国Linux 内核 6.1 发布,包含初始 Rust 支持 | Linux 中国2023年卫生资格考试报名时间及考试时间公布!文末送书 | 入门SLAM优选好书!视觉惯性SLAM:理论与源码解析为黑五剁手暖暖场如何增进视力免费开源 虚拟机 VirtualBox 7.0.6 发布,初步支持 Linux 6.2 等内核3月起联邦停发纽约粮食券额外金额,权益团体支招如何增加福利技术分析:美股四大指数亟待突破支撑位,回旋空间有限?来了来了,走了走了。。。Linux 只是一个内核:这是什么意思? | Linux 中国简化版的肠镜检查
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。