跳至正文
Wener Notes

Linux 内存管理 (Memory Management)

约 5 分钟阅读
标签:LinuxMemoryKernelMMUVirtualMemory
abbr.stand formeaning
THPTransparent Huge Page透明大页
VMAVirtual Memory Area虚拟内存区域
TLBTranslation Lookaside Buffer转换后备缓冲区
UFFDUserfaultfd用户态页错误处理
PTEPage Table Entry页表项
PFNPage Frame Number页框号
MMUMemory Management Unit内存管理单元
wpWrite Protect写保护
pmPage Map页面映射

  • /proc/pid/pagemap
    • fs/proc/task_mmu.c, pagemap_read
    • CAP_SYS_ADMIN
    • PFN - Page Frame Number
    • ioctl PAGEMAP_SCAN struct pm_scan_arg
      • PAGE_IS_WPALLOWED - 页面已启用异步写保护
      • PAGE_IS_WRITTEN - 页面自写保护以来已被写入
      • PAGE_IS_FILE - 页面是文件支持的
      • PAGE_IS_PRESENT - 页面存在于内存中
      • PAGE_IS_SWAPPED - 页面已被交换
      • PAGE_IS_PFNZERO - 页面具有零 PFN
      • PAGE_IS_HUGE - 页面是 PMD 映射的 THP 或 Hugetlb 支持的
      • PAGE_IS_SOFT_DIRTY - 页面是软脏的
  • /proc/pid/maps
  • /proc/kpagecount
    • 64bit counter
    • 页面被映射的次数,按 PFN 索引
  • /proc/kpageflags
    • fs/proc/page.c,kpageflags_read
  • /proc/kpagecgroup

Usage

itemstand for
rss匿名内存 / heap / stack / mmap 后实际驻留的内存
page cache读文件、写文件、加载 mmap - 可回收内存
inactive_file不活跃的文件缓存
kernel/cgroup内核 / cgroup 内存使用
working_set工作集 usage - inactive_file
usage内存使用量
anon匿名内存 / heap / stack / mmap 后实际驻留的内存
file读文件、写文件、加载 mmap - 可回收内存
inactive_file不活跃的文件缓存
active_file活跃的文件缓存
dirty脏页
writeback回写页
slab内核 slab 分配器内存
ffor
/sys/fs/cgroup/memory.current
/sys/fs/cgroup/memory.stat
/sys/fs/cgroup/memory.max
text
container_memory_working_set_bytes = Usage - inactive_file

container_memory_rss = 匿名内存 / heap / stack / mmap 后实际驻留的内存


不活跃的文件缓存
container_memory_total_inactive_file_bytes = usage - working_set

内存泄漏

  • RSS ↑
  • Working Set ↑
  • Go Heap ↑
  • Page Cache 不高

Linux 文件缓存 / IO 行为

  • Usage ↑
  • Page Cache ↑
  • inactive_file ↑
  • usage - working_set ↑
  • RSS / Go Heap 稳定

参考

启动时物理内存概念布局

此表概述了在 x86-64 系统启动时,主内核内存管理激活之前,物理 RAM 的前几兆字节是如何按顺序使用的。

物理地址范围(约)阶段描述
0x00000000 - 0x0009FFFF(前 640 KB)BIOS/UEFI 和引导加载程序这是"常规内存"区域。系统 BIOS/UEFI 使用此区域的部分用于其数据和中断向量。引导加载程序(如 GRUB)被加载到此处并开始执行。
0x000A0000 - 0x000FFFFF硬件和 BIOS ROM保留给硬件使用,如视频缓冲区和 BIOS ROM 映射。
0x00100000(1 MB)及以上内核加载引导加载程序将压缩的内核映像和初始 RAM 磁盘(initramfs)加载到物理内存的这个区域。
变化(低内存)早期内核数据内核的初始页表和引导时内存管理器(memblock)的数据结构在低物理内存中设置,用于在最终内存管理初始化之前管理系统的内存映射。

内核虚拟地址空间布局(x86-64,4 级分页)

一旦内核在 64 位长模式下运行,它就会建立虚拟地址空间。当前的 x86-64 CPU 使用 48 位虚拟地址,创建一个巨大的 256 TB 空间,该空间在用户应用程序和内核本身之间分配。

虚拟地址范围区域描述
0x0000000000000000 - 0x00007FFFFFFFFFFF用户空间(128 TB)整个下半部分可供用户进程使用。每个进程在此范围内都有自己的独立映射。此空间内的布局在表 3 中详述。
0x0000800000000000 - 0xFFFF7FFFFFFFFFFF非规范"空洞"这个巨大的间隙未被使用。CPU 强制所有有效地址的高 16 位必须全为零(用户空间)或全为一(内核空间)。
0xFFFF800000000000 - 0xFFFFFFFFFFFFFFFF内核空间(128 TB)上半部分保留给内核。它大部分是恒定的,并映射在每个进程的地址空间中,尽管它受到保护,不允许用户模式访问。
0xFFFF880000000000 - 0xFFFFC7FFFFFFFFFF(内核空间内)直接内存映射这个 64 TB 区域是系统所有物理 RAM 的直接线性映射。这里的内核逻辑地址可以通过简单地减去偏移量转换为物理地址。这允许对任何物理页面进行快速、高效的访问。
变化(内核空间内)vmalloc 和 ioremap 区域用于分配可能物理上分散的虚拟连续内存(vmalloc)和将硬件设备内存映射到内核地址空间(ioremap)。
变化(内核空间内)内核文本、数据、BSS内核本身的实际代码和静态数据被加载到此处。内核映像通常放置在此区域的顶部。
变化(内核空间内)特殊映射包括 EFI 运行时服务的区域,仅在需要时映射。

用户空间虚拟地址布局(典型进程)

此表显示了单个运行程序在 128 TB 用户空间区域内的标准布局。确切的地址通过地址空间布局随机化(ASLR)进行随机化以提高安全性。

区域描述增长方向
文本段(.text)程序的可执行代码。映射为只读和可执行。64 位程序的默认起始地址通常是 0x400000。静态
数据段(.data,.bss)存储已初始化(.data)和未初始化(.bss)的全局和静态变量。静态
堆动态分配的内存,由 malloc() 和 brk() 等函数管理。用于必须超出创建它的函数调用生存期的数据。向上增长(朝向更高地址)
内存映射段用于内存映射文件和由动态链接器加载的共享库(.so 文件)。大的 malloc 分配也可能使用此区域。变化
栈存储局部变量、函数参数和函数调用的返回地址。进程中的每个线程都有自己的栈。向下增长(朝向更低地址)
vDSO 和 [vsyscall]虚拟动态共享对象。内核暴露的一个小内存区域,用于加速某些系统调用(如 gettimeofday),而无需上下文切换的完整开销。静态(地址随机化)
内核空间虚拟地址空间的上 128 TB 为内核映射,但用户模式无法访问。静态

物理内存区域

内核进一步将物理内存划分为逻辑"区域",以处理硬件限制,特别是直接内存访问(DMA)。这些不是地址范围,而是物理页面的逻辑分组。

区域名称描述
ZONE_DMA包含物理内存前 16 MB 内的页面。旧的 ISA 设备需要此区域,这些设备只能在此有限范围内执行 DMA。
ZONE_DMA32在 64 位系统上,包含前 4 GB 内的页面。用于 32 位设备,这些设备可以对 32 位范围内的任何地址执行 DMA,但不能在完整的 64 位空间内执行。
ZONE_NORMAL包含内核直接映射的所有"正常"物理内存。在 64 位系统上,这涵盖了大部分 RAM。这是大多数内核分配的首选区域。
ZONE_HIGHMEM(主要是 32 位架构)~896 MB 标记以上的内存,未永久映射到内核的地址空间中。访问它需要创建临时映射(kmap())。
ZONE_MOVABLE包含内核可以移动其物理位置的页面。这对于减少内存碎片和支持内存热插拔至关重要。
ZONE_DEVICE表示设备上的内存,如持久内存(PMEM)或 GPU,这些设备具有与标准 RAM 不同的特性。

关联信息

反向链接、本文链接的其他页面和外部资料。

站内链接

  • hugetlbpage
    笔记 · hugetlbpage

    Translation Lookaside Buffer, TLB · 2MB,1GB · 减少 TLB 压力 · 提升性能 · 锁定内存 - 不可交换 · /proc/sys/vm/nrhugepages · hugepages=N · 预留多少页

  • sys/mman.h
    笔记 · mman.h

    内存管理 · 参考 · https://git.musl-libc.org/cgit/musl/tree/include/sys/mman.h · https://github.com/kraj/musl/blob/kraj/master/include/sys/mman.h

参考资料

Wikipedia1 条
其他外链4 条
最近更新commit be2511e编辑