kmem

crash> kmem -p

  PAGE    PHYSICAL   MAPPING    INDEX CNT FLAGS
c09d0000  82000000  edc023a0      3000  2 860
c09d0020  82001000  edc025a0         0  2 860
c09d0040  82002000         0        83  1 0
c09d0060  82003000  ede59ba0       2b7  1 20228

_count:CNT
A usage reference counter for the page. If it is set to -1, the corresponding page frame is free
and can be assigned to any process or to the kernel itself. If it is set to a value greater than or
equal to 0, the page frame is assigned to one or more processes or is used to store some
kernel data structures. The page_count( ) function returns the value of the _count field
increased by one, that is, the number of users of the page.

flags:FLAGS
Includes up to 32 flags (see Table 8-2) that describe the status of the page frame. For each
PG_ xyz flag, the kernel defines some macros that manipulate its value. Usually, the PageXyz
macro returns the value of the flag, while the SetPageXyz and ClearPageXyz macro set and
clear the corresponding bit, respectively.

PAGE:
crash> mem_map
mem_map = $3 = (struct page *) 0xc09d0000
crash> page
struct page {
    unsigned long flags;
    struct address_space *mapping;
    struct {
        union {
            unsigned long index;
            void *freelist;
        };
        union {
            unsigned long counters;
            struct {
                union {
                    atomic_t _mapcount;
                    struct {
                        unsigned int inuse : 16;
                        unsigned int objects : 15;
                        unsigned int frozen : 1;
                    };
                };
                atomic_t _count;
            };
        };
    };
    union {
        struct list_head lru;
        struct {
            struct page *next;
            short pages;
            short pobjects;
        };
    };
    union {
        unsigned long private;
        struct kmem_cache *slab;
        struct page *first_page;
    };
}
SIZE: 32

crash> struct page -o
struct page {
   [0] unsigned long flags;
   [4] struct address_space *mapping;
       struct {
           union {
   [8]         unsigned long index;
   [8]         void *freelist;
           };
           union {
  [12]         unsigned long counters;
               struct {
                   union {
  [12]                 atomic_t _mapcount;
                       struct {
  [12]                     unsigned int inuse : 16;
  [12]                     unsigned int objects : 15;
  [12]                     unsigned int frozen : 1;
                       };
                   };
  [16]             atomic_t _count;
               };
           };
       };
       union {
  [20]     struct list_head lru;
           struct {
  [20]         struct page *next;
  [24]         short pages;
  [26]         short pobjects;
           };
       };
       union {
  [28]     unsigned long private;
  [28]     struct kmem_cache *slab;
  [28]     struct page *first_page;
       };
}

SIZE: 32

crash> kmem -s

CACHE    NAME                 OBJSIZE  ALLOCATED     TOTAL  SLABS  SSIZE
ee0004e0 size-16384             16384         20        21     21    16k

crash> kmem_cache
struct kmem_cache {
    unsigned int batchcount;
    unsigned int limit;
    unsigned int shared;
    unsigned int buffer_size;
    u32 reciprocal_buffer_size;
    unsigned int flags;
    unsigned int num;
    unsigned int gfporder;
    gfp_t gfpflags;
    size_t colour;
    unsigned int colour_off;
    struct kmem_cache *slabp_cache;
    unsigned int slab_size;
    unsigned int dflags;
    void (*ctor)(void *);
    const char *name;
    struct list_head next;
    struct kmem_list3 **nodelists;
    struct array_cache *array[2];
}
SIZE: 84

crash> kmem_cache ee0004e0

struct kmem_cache {
  batchcount = 4,
  limit = 8,
  shared = 0,
  buffer_size = 16384,
  reciprocal_buffer_size = 262144,
  flags = 2147753984,
  num = 1,
  gfporder = 2,
  gfpflags = 0,
  colour = 0,
  colour_off = 32,
  slabp_cache = 0xee0000c0,
  slab_size = 32,
  dflags = 0,
  ctor = 0x0,
  name = 0xc0678ded "size-16384",
  next = {
    next = 0xee0004c0,
    prev = 0xee000580
  },
  nodelists = 0xee000534,
  array = {0xee0081a0, 0xee045f20}
}

crash>  kmem_list3

struct kmem_list3 {
    struct list_head slabs_partial;
    struct list_head slabs_full;
    struct list_head slabs_free;
    unsigned long free_objects;
    unsigned int free_limit;
    unsigned int colour_next;
    spinlock_t list_lock;
    struct array_cache *shared;
    struct array_cache **alien;
    unsigned long next_reap;
    int free_touched;
}
SIZE: 60

crash> rd 0xee000534
ee000534:  ee002360

crash> kmem_list3 ee002360
struct kmem_list3 {
  slabs_partial = {
    next = 0xee002360,
    prev = 0xee002360
  },
  slabs_full = {
    next = 0xdc89b6a0,
    prev = 0xee10fdc0
  },
  slabs_free = {
    next = 0xee002370,
    prev = 0xee002370
  },
  free_objects = 0,
  free_limit = 9,
  colour_next = 0,
  list_lock = {
    {
      rlock = {
        raw_lock = {
          lock = 0
        },
        break_lock = 0
      }
    }
  },
  shared = 0x0,
  alien = 0x0,
  next_reap = 134200,
  free_touched = 1
}

crash> slab

struct slab {
    union {
        struct {
            struct list_head list;
            unsigned long colouroff;
            void *s_mem;
            unsigned int inuse;
            kmem_bufctl_t free;
            unsigned short nodeid;
        };
        struct slab_rcu __slab_cover_slab_rcu;
    };
}
SIZE: 28

crash> slab dc89b6a0
struct slab {
  {
    {
      list = {
        next = 0xc2fe5960,
        prev = 0xee002368
      },
      colouroff = 0,
      s_mem = 0xd5fa0000,
      inuse = 1,
      free = 4294967295,
      nodeid = 0
    },
    __slab_cover_slab_rcu = {
      head = {
        next = 0xc2fe5960,
        func = 0xee002368
      },
      cachep = 0x0,
      addr = 0xd5fa0000
    }
  }
}

crash> kmem -S size-16384

CACHE    NAME                 OBJSIZE  ALLOCATED     TOTAL  SLABS  SSIZE
ee0004e0 size-16384             16384         20        21     21    16k

/*1*/
SLAB      MEMORY    TOTAL  ALLOCATED  FREE
dc89b6a0  d5fa0000      1          0     1
FREE / [ALLOCATED]
   d5fa0000  (cpu 0 cache)




<think>嗯,用户想了解simpleperf中kmem的使用方法。根据引用内容,kmem是simpleperf的一个子命令,用于收集内核内存分配信息。用户可能正在做性能优化相关的工作,特别是内存方面的分析。 先整理已知信息:引用[4]中明确列出了kmem子命令,但未提供详细用法。需要结合simpleperf的通用语法和内存分析特性来构建回答。考虑到用户是发者,应该提供可操作的命令行示例。 用户可能遇到的具体场景包括:分析Android应用的内存瓶颈、追踪内核slab分配、定位内存泄漏等。回答需要覆盖基础命令格式、常用参数和典型用例。由于引用[3]提供了官方文档链接,应该引导用户查阅更完整的参数说明。 要注意避免术语堆砌,用$符号包裹命令行参数如$--call-graph,保持LaTeX格式要求。内存分析涉及内核机制,需提醒权限要求(如adb root)。 最后生成的问题要围绕内存分析场景:如何解读kmem输出、火焰图生成、对比其他工具等,这些都能帮助用户深化排查能力。特别是内存泄漏检测场景,发者实际需求可能隐含其中。</think>在 `simpleperf` 中,`kmem` 子命令用于收集和分析内核内存分配事件(如 kmalloc, kfree, mm_page_alloc, mm_page_free 等)。这有助于诊断内核空间的内存使用情况、内存泄漏或分配热点问题。 **基本使用方法:** 1. **确保设备具有 root 权限:** `kmem` 需要访问内核事件,通常需要 root 权限。 ```bash adb root ``` 2. **列出可用的 kmem 事件:** 使用 `simpleperf list` 查看内核支持哪些内存分配事件。 ```bash simpleperf list kmem ``` 输出会显示类似 `kmem:kmalloc`, `kmem:kfree`, `kmem:mm_page_alloc`, `kmem:mm_page_free` 等事件及其描述。 3. **收集内存分配数据:** 使用 `simpleperf kmem record` 命令始记录选定的内核内存事件。 * **基本命令格式:** ```bash simpleperf kmem record [options] [--duration <seconds>] [command] ``` * **常用选项:** * `-e <event1>,<event2>,...`:指定要记录的事件(如 `-e kmem:kmalloc,kmem:kfree`)。 * `-g`:启用调用图(call graph)记录,这对于分析分配堆栈至关重要。 * `--call-graph <fp|dwarf[,<limit>]>`:指定调用图记录方法(`fp` 帧指针或 `dwarf`)和可选的堆栈深度限制(如 `--call-graph dwarf,8`)。 * `-o <output_file>`:指定输出数据文件名(默认为 `perf.data`)。 * `--duration <seconds>`:记录持续多少秒。 * `[command]`:在记录期间启动并分析的应用程序或命令。 * **示例:** * 记录所有 `kmem` 事件 10 秒: ```bash simpleperf kmem record --duration 10 ``` * 记录 `kmalloc` 和 `kfree` 事件,启用调用图(使用 dwarf 回溯,深度 8),输出到 `mem.data`,并在记录期间运行 `ls`: ```bash simpleperf kmem record -e kmem:kmalloc,kmem:kfree -g --call-graph dwarf,8 -o mem.data ls ``` 4. **分析记录的数据:** 使用 `simpleperf kmem report` 命令生成报告。 * **基本命令格式:** ```bash simpleperf kmem report [options] [-i <perf_data_file>] ``` * **常用选项:** * `-i <input_file>`:指定输入的记录数据文件(默认为 `perf.data`)。 * `-n`:显示每个样本的调用链(需要记录时启用了 `-g`)。 * `--sort <key1[,key2,...]>`:指定报告排序的列(如 `comm,pid,tid,event,dso,symbol`)。 * `--children`:在调用图中显示累积计数(函数自身 + 其子函数)。 * `-g`:在报告中显示调用图(需要记录时启用了 `-g`)。 * **示例:** * 生成默认报告: ```bash simpleperf kmem report -i mem.data ``` * 生成报告,显示每个样本的调用链(按触发事件的堆栈排序): ```bash simpleperf kmem report -i mem.data -n ``` * 生成报告,按命令名和符号名排序,并显示调用图: ```bash simpleperf kmem report -i mem.data --sort comm,symbol -g ``` **报告解读:** 报告通常包含以下关键列: * `Overhead`:该事件(或调用链)占总样本数的百分比。 * `Samples`:该事件(或调用链)捕获的样本数量。 * `Event`:发生的事件类型(如 `kmem:kmalloc`)。 * `Command`:触发事件的进程名(comm)。 * `Pid` / `Tid`:进程 ID / 线程 ID。 * `Shared Object`:发生事件的动态库或内核模块(dso)。 * `Symbol`:发生事件的函数名。 * `Callchain`:触发事件的函数调用堆栈(当使用 `-n` 或 `-g` 时)。 **重点分析方向:** 1. **高分配率函数/模块:** 查找 `Overhead` 或 `Samples` 高的 `Symbol` 或 `Shared Object`,这可能是内存分配热点或潜在泄漏点。 2. **分配/释放不平衡:** 比较 `kmalloc` 和 `kfree` 事件的数量(特别是针对特定大小或特定调用点),显著不平衡可能指示内存泄漏。 3. **调用链分析:** 使用 `-n` 或 `-g` 查看完整的分配堆栈。这能精确定位到是哪个用户态进程/线程、通过哪个系统调用、最终在内核的哪个驱动/子系统中触发了大量分配。这是诊断问题的关键。 **注意事项:** * **权限:** `kmem` 需要 root 权限 (`adb root`)。 * **内核支持:** 需要内核启用 `CONFIG_KPROBE_EVENTS` 或 `CONFIG_TRACEPOINTS` 等特性来暴露所需事件。 * **性能销:** 记录内核事件,尤其是调用图 (`-g`),会带来显著性能销,可能影响被分析程序的运行。谨慎选择记录时长和事件范围。 * **符号解析:** 确保设备上有对应内核版本的符号文件(`vmlinux` 或带调试符号的内核模块),否则报告中可能只有地址而非有意义的函数名。这通常需要编译内核时保留调试符号。 * **详细参数:** 更多高级选项(如过滤特定 PID、大小、分配标志等)请参考官方文档:https://android.googlesource.com/platform/system/extras/+/master/simpleperf/doc/executable_commands_reference.md#kmem[^3]。 **总结步骤:** 1. `adb root` 2. `simpleperf list kmem` (查看可用事件) 3. `simpleperf kmem record -e <events> -g ... -o <file> ...` (记录数据) 4. `simpleperf kmem report -i <file> -n` (分析调用链) 或 `simpleperf kmem report -i <file> -g` (分析调用图)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值