Skip to main content
Linux 使用虚拟内存系统。因此,用户程序访问的地址并不直接对应硬件使用的物理地址。虚拟内存引入了一层间接机制,允许程序分配超出物理可用内存的额外内存。 内存管理的实现涵盖以下方面:
  • 管理内存中的物理页
  • 用于以大块分配内存的伙伴(buddy)系统
  • 用于分配较小内存块的 slab、slub 和 slob 分配器
  • 用于分配非连续内存块的 vmalloc 机制
  • 进程的地址空间

/proc 文件系统

/proc 文件系统提供以下文件:

/proc/meminfo

此文件提供有关内存分布和使用情况的信息。
  • 要查看此文件的内容,请运行以下命令:
    示例输出:
有关此文件中可用参数的更多信息,请参阅 /proc 文件系统

/proc/vmstat

此文件显示来自内核的详细虚拟内存统计信息。大多数统计信息仅在您于 init/Kconfig 文件中启用 CONFIG_VM_EVENT_COUNTERS 选项后才可用。
  • 要查看此文件的内容,请运行以下命令:
    示例输出:
有关此文件中可用参数的更多信息,请参阅 Linux 手册页

/proc/iomem

此文件显示系统中各种设备驱动程序的内存映射。
  • 要查看此文件的内容,请运行以下命令:
    示例输出:

/proc/vmallocinfo

此文件显示通过 vmallocioremap 进行的虚拟地址分配的详细信息。
  • 要查看此文件的内容,请运行以下命令:
    示例输出:

memblock 接口

debugfs 文件系统上的 memblock 接口提供系统中可用和保留内存区域的详细信息。该接口提供以下文件:

/sys/kernel/debug/memblock/memory

此文件提供 Linux 内核可见的所有可用内存区域(HLOS 和非 HLOS)的信息。要确定内核可访问的总内存,请计算每个区域起始地址与结束地址之间的差值,并将这些值求和以得到已占用的 RAM 总量。剩余的内存(即设备 RAM 大小与已占用 RAM 之间的差值)为非 HLOS 内存,或被其他子系统占用的内存。
  • 要查看此文件的内容,请运行以下命令:
    示例输出:

/sys/kernel/debug/memblock/reserved

此文件提供系统中所有保留内存区域的信息。
  • 要查看此文件的内容,请运行以下命令:
    示例输出:

调试内存泄漏问题

要调试内核内存泄漏问题,请启用以下配置选项:
  • CONFIG_DEBUG_KMEMLEAK=y
  • CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE=4000
  • CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
默认情况下,一个内核线程每 10 分钟扫描一次内存,并打印发现的新的未被引用对象的数量。例如,
通过在内核命令行上传递 KMEMLEAK=off,可以在启动时禁用 KMEMLEAK 选项。 有关 kmemleak.txt 文件的更多信息,请参阅内核文档 以下额外的内核配置选项可用于跟踪每个内存页的分配者:
  • CONFIG_PAGE_OWNER
  • CONFIG_PAGE_OWNER_ENABLE_DEFAULT
  • CONFIG_PAGE_EXTENSION
启用这些选项有助于识别多次分配的情况,这可能表明存在内存泄漏问题。

识别内存损坏问题

启用以下内核配置选项以识别内存损坏问题:
  • CONFIG_PAGE_POISONING
  • CONFIG_SLUB_DEBUG_ON
  • CONFIG_DEBUG_LIST
  • CONFIG_SLUB_DEBUG
示例日志:
有关 slub 调试的更多信息,请参阅内核文档中提供的 Documentation/vm/slub.txt 文件。

内存不足

当系统无法分配页面时,内核日志会显示类似以下的消息:
这些消息表明系统无法分配所请求的页面。日志消息的第一行提供了有关内存不足问题的若干详细信息。例如,在以下日志中:
  • order:表示页面的大小。在此示例中,2 2 x PAGE_SIZE(4 K)= 16 K
    • Linux 使用以 2 的幂分配页面的伙伴分配器。
      • 伙伴分配器的最大大小为 order 10 = 2 10 x 4 kB = 4 MB。
      • 对于 > 4 MB 的分配,请使用替代分配方法,例如连续内存分配器(CMA)。
    • 对于高阶(higher-order)分配失败,请检查内存是否可以在虚拟上连续,而不必在物理上连续。
  • mode:表示所请求页面的类型
    • mode 提供有关获取空闲页(GFP)标志的信息。在此示例中,mode0x10d2
    • mode 是对分配中所有 GFP 标志执行 OR 运算的结果。
  • 系统中可用的页面:页面分配失败消息会打印系统中可用页面大小的详细信息。

IOMMU 页面错误

输入输出内存管理单元(IOMMU),也称为系统内存管理单元(SMMU),代表没有自己 MMU 的子系统执行内存管理功能。 IOMMU 硬件模块允许物理上非连续的页面支持虚拟上连续的内存。IOMMU 中的内存转换逻辑与 CPU MMU 中的逻辑相同。 IOMMU 页面错误是最常见的 IOMMU 问题。当所请求的页面已在页表中映射但在内存中未找到时,会发生该错误。错误处理程序接收 IOMMU 的上下文库(context bank)实例,并转储该上下文的寄存器。 以下日志表示 IOMMU 页面错误。
下表描述了日志消息中捕获的字段。 表:IOMMU 页面错误日志中的信息
  • 转换故障(TF)
  • 访问权限故障(APF)
  • 停滞状态(SS)
FSR 是 IOMMU 调试中最重要的寄存器之一。该寄存器具有读/写清除(read/write-clear)访问权限。对该寄存器的读操作读取寄存器中的值,而写操作会清除写入数据中为 1 的位所对应的位,并使为 0 的位所对应的位保持不变。此过程可防止在写入寄存器以清除旧故障时意外清除新故障。该寄存器中一些有用的位如下: 表:故障状态寄存器中的位 TFAPFSL 标志表示正常操作,而 TLBMFHTWDEEFHTWSEEFMHF 标志表示存在问题。

IOMMU 页表

IOMMU 页表转储在内核日志中提供来自 FAR 的故障地址和寄存器转储。该故障地址代表虚拟地址,您可以从页表中获取对应的物理地址。从页表转储中,您可以识别所请求的地址是已映射还是未映射。每个 IOMMU 域都有一个页表,转储包括每个域的页表。目前有六个域。 以下是 Domain: 2 页表的示例转储。
在此示例中,第一列代表虚拟地址,第二列代表对应的连续物理地址区域中的字节数,第三列代表物理地址。每个区域的权限也一并列出。

内存映射

有关内存映射的更多信息,请参阅最新的发行说明

栈损坏

错误的编码逻辑访问栈中的内存位置,导致这些内存位置的值发生变化,从而造成栈损坏。栈损坏可能以以下方式发生:
  • 由于错误的代码逻辑,程序耗尽所有栈内存并写入超出栈边界的内存,导致栈溢出。
  • 访问越界的数组。
  • 未定义或已释放的指针指向栈地址。
  • 调用者函数的返回地址被损坏。
要识别栈损坏问题,请启用以下内核配置选项:
  • CONFIG_STACKPROTECTOR
  • CONFIG_STACKPROTECTOR_STRONG
内核地址消毒器(KASAN)实用工具也有助于识别某些栈损坏问题。