mmap 和虚拟内存
mmap 和虚拟内存
mmap 和虚拟内存
一个有趣的实验
程序
构造一个非常大的 libbloat.so
我们的例子:100M of nop (0x90)
实验
创建 1,000 个进程动态链接 libbloat.so 的进程
观察系统的内存占用情况
100MB or 100GB?
(如果是后者,直播会立即翻车)
Prototypes are easy. Production is hard. (Elon Musk)
mmap 和虚拟内存
共享库的加载
计算机世界里没有魔法
你总能溯源到正确的行为
a.out (动态链接) 的第一条指令不在程序里
可以 starti 验证 (在 ld.so 里)
这是 “写死” 在 ELF 文件的 INTERP (interpreter) 段里的
(我们甚至可以直接编辑它)
a.out 执行时,libc 还没有加载
可以 info proc mappings (pmap) 验证
libc 是用 mmap 系统调用加载的
可以 strace 验证
只读方式 mmap 同一个文件,物理内存中只有一个副本
mmap 和虚拟内存
背后的机制:虚拟内存管理
地址空间表面是 “若干连续的内存段”
通过 mmap/munmap/mprotect 维护
实际是分页机制维护的 “幻象”
mmap 和虚拟内存
操作系统的 Tricks (1)
Virtual Memory
操作系统维护 “memory mappings” 的数据结构
这个数据结构很紧凑 (“哪一段映射到哪里了”)
延迟加载
不到万不得已,不给进程分配内存
写时复制 (Copy-on-Write)
fork() 时,父子进程先只读共享全部地址空间
Page fault 时,写者复制一份
mmap 和虚拟内存
操作系统的 Tricks (2)
Memory Deduplication; Compression & Swapping
反正都是虚拟内存了
悄悄扫描内存
如果有重复的 read-only pages,合并
(如果硬件提供 page hash 就更好了)
悄悄扫描内存
发现 cold pages,可以压缩/swap 到硬盘
(硬件提供了 Access/Dirty bit)
我们还能悄悄扫描内存做什么?
看看 AIGC 的答案吧!