scudo基础学习

Scudo 是一个动态内存分配器,优势在于安全性,可以检测到一些内存漏洞(eap-overflow,double-free,use-after-free),但牺牲了一些性能

从Android11开始,Scudo负责所有用户空间native(c,c++)内存分配和释放:

(备注:

  1. java/kotlin层常用bump allocator、buddy allocator分配内存
  2. kernel主要采用slab和boot memory allocator

Linux Memory -- 三大allocator原理_offsetallocator-CSDN博客

Scudo 定义了 Primary 和 Secondary 两种类型分配器:

  • Primary Allocator :小于64 k时使用 Primary Allocator (分配小内存
  • Secondary Allocator:大于 64 k 使用 Secondary Allocator (分配大内存 ), 使用mmap分配

Scudo初始化之后会预先分配33个内存区域( SizeClass:一个region )的虚拟内存,0号region 用于存放内存管理元数据,每个 SizeClass 提供大小X的内存分配,每个 SizeClass mmap 256M的虚拟内存,分成大小相同的

多块内存。

SizeClass最小是32 Bytes,依次48 Bytes ,64 Bytes ... ,定义如下 ./external/scudo/standalone/primary64.h:

复制代码
static constexpr u32 Classes[] = {
      0x00020, 0x00030, 0x00040, 0x00050, 0x00060, 0x00070, 0x00090, 0x000b0,
      0x000c0, 0x000e0, 0x00120, 0x00160, 0x001c0, 0x00250, 0x00320, 0x00450,
      0x00670, 0x00830, 0x00a10, 0x00c30, 0x01010, 0x01210, 0x01bd0, 0x02210,
      0x02d90, 0x03790, 0x04010, 0x04810, 0x05a10, 0x07310, 0x08210, 0x10010,
  };

分配规则: 申请的内存大小从小到大选择合适的Region:先从32 Bytes 开始,如果不能分配就从48 Bytes ,64 Bytes......65552Bytes(64kb)

关键log:

某个region (SizeClass)内存申请完了(超过256M),系统会提示Scudo OOM: The process has exhausted 256M for size class 并且打印出每个SizeClass使用现状,如下所示:

scudo : Stats: SizeClassAllocator64: 8053M mapped (0M rss) in 8370721712 allocations; remains 32047130

有些误解:

  • 每个进程申请的虚拟内存大小是固定的?

❌,没有限制(javaHeap 有限制,NativeHeap 没有限制,每个进程的vma个数vm.max_map_count )是有限制的),可以通过命令查到 sysctl -a|grep vm.max_map_count

大多数进程只用32个vma,一般不会超过。1个SizeClass就是一个vma,但vma的虚拟内存大小是没有限制的 ,所以整体可以理解成无限制的,本地demo实验证明 22G 车机上能分配到16G native内存。

  • 每个Scudo分配的内存上限是固定的?

❌,Primary Allocator(SizeClassAllocator64)申请的内存是有限的,Secondary Allocator申请的内存是无限的

Primary Allocator能分配的最大内存为8G(32*256M),如果分配完了,再申请64kb下的内存会报错Scudo ERROR: internal map failure (NO MEMORY) requesting

Secondary Allocator内部有的Cache最多缓存 32 个不超过 2M 的 VMA(32*2M),但分配的总量是无限制的,只有系统内存不足时才会分配失败

  • Scudo分配失败一定是系统内存不足?

❌,如果Primary Allocator满了,申请小内存也会失败

TSD(Thread Specific Data)

为了解决多线程下内存的分配加锁导致的性能问题,为每个线程分配一块专有的内存(TSD),由于Android 系统 TSD 的数量有限 ,默认有2个 TSD ,采用负载均衡算法实现同步

错误排查:

scudo : Scudo ERROR: internal map failure (NO MEMORY) requesting

ibc : pthread_create failed: couldn't allocate'

ibc :malloc(4096) failed: returning null pointer

原因分析:map发生快速内存泄漏,导致分配器分配不出更多内存

参考文献:

https://zhuanlan.zhihu.com/p/235620563
https://zhuanlan.zhihu.com/p/560188790
https://zhuanlan.zhihu.com/p/423062509
Android内存分配-Scudo内存分配器 - 简书
https://zhuanlan.zhihu.com/p/604315376
https://zhuanlan.zhihu.com/p/644169143
Scudo | Android Open Source Project

相关推荐
xcLeigh2 天前
把CPU、内存、网络流量同时丢给TimechoAI,做交叉分析
数据库·内存·时序数据库·cpu·网络流量·timechoai·交叉分析
深念Y5 天前
SSD 寿命洁癖:编译过程不入盘的原则与实践
缓存·io·内存·编译·ssd·读取·写入
core5127 天前
一次“内存持续增长“的排查复盘:从怀疑 HttpClient 连接泄漏到确认堆页预热
内存·httpclient·泄露·arthas·连接
深念Y7 天前
系统内存与Swap优化记录
linux·内存·优化·虚拟内存·压缩·ram·zram
XLYcmy12 天前
小红书 算法一面 二
llm·sft·memory·多模态·位置编码·grpo·视觉数据
orient.lu12 天前
第 15 章《记忆与 Dream 整合》· nanobot Dream 记忆整合源码深度解析:真实 git diff 当 commit message
memory·nanobot
liulilittle13 天前
LLM 推理引擎与内核系统工程原理
c++·ai·llm·内存·memory·core·kernel
AmyLin_200119 天前
PDF 色彩保真工程实践【6】怎么证明“真的无损“?——SHA-256 校验与三个真实踩坑
c++·pdf·内存·sdk·调试·印刷
zzz_236819 天前
TencentDB-Agent-Memory 深度解析:让多个 Agent 共享项目经验的记忆中枢
java·开发语言·jvm·人工智能·agent·memory·tencent db
UWA22 天前
隐藏视频变“常驻刺客”,VideoPlayer与“N/A”纹理该怎么查
人工智能·性能优化·音视频·memory·cpu·游戏开发