perf kmem获取内存分配信息的核心是依赖内核预设的 tracepoint跟踪点。它本身并不直接“读内存”而是作为一个用户态消费者去监听内核在内存分配/释放时主动“广播”出来的事件。原理监听内核的“广播”内核在mm/slab.c、mm/page_alloc.c等关键路径中埋设了静态跟踪点tracepoint。当发生内存分配或释放时这些跟踪点会被触发并携带一组预定义的字段输出到环形缓冲区ring buffer。perf kmem通过perf_event_open系统调用订阅这些事件从而获取原始数据。获取的具体信息根据分析的对象不同Slab 或 Pageperf kmem获取的信息分为两类1. Slab 分配--slab默认监听kmalloc、kmem_cache_alloc等事件获取的字段包括call_site调用分配函数的指令地址内核符号偏移。这是定位“谁在分配”的关键。ptr返回的内存指针。bytes_req调用者请求的字节数。bytes_allocSlab 实际分配的字节数。gfp_flags分配标志如GFP_KERNEL反映分配上下文。perf kmem拿到bytes_req和bytes_alloc后相除就能计算出碎片率Fragmentation。2. 页分配--page监听mm_page_alloc、mm_page_free等事件获取page/pfn页描述符指针或页帧号。order分配阶数决定是单个页还是连续的大块内存。migratetype迁移类型如MIGRATE_UNMOVABLE。gfp_flags分配标志。数据加工从原始事件到统计报表perf kmem拿到原始事件后会做几件关键的事情符号解析把call_site的地址转换成可读的内核函数名如__kmalloc这正是它默认从运行内核获取符号信息的原因。关联与聚合对于 Slab它把ptr相同的kmalloc和kfree事件关联起来从而判断一块内存是否仍存活用于识别泄漏。对于 Page它维护一个页状态表跟踪每一页的分配与释放。计算衍生指标比如用bytes_alloc减bytes_req算出内部碎片量或者统计某个调用点的总分配次数。最终这些信息被聚合成你perf kmem stat看到的表格每一行就是一个call_site调用点的汇总统计。