Rockchip · AI & Linux Hub

Linux и загрузка

Отладка памяти Rockchip Linux: meminfo, slab, memblock и давление памяти

Все команды диагностики памяти, код ядра, журналы и определения полей с отмеченными противоречиями исходника.

· ArmSoM Editorial · Rockchip source documentation · 15 мин чтения

Применимость к ArmSoM и источник

Справочный материал для адаптации ArmSoM, переведённый с китайского V1.0.0. Область исходника: ARM, Linux 4.19. Английский PDF отсутствует; английская, русская и немецкая версии полностью переведены с китайского. Немецкая использует те же изображения, что английская статья. Конкретные платы ArmSoM, SDK/BSP и сочетания драйверов не подтверждены и аппаратно не проверены. Сверьте SoC, карту памяти платы, SDK/BSP, конфигурацию ядра и реализацию драйвера. Код, адреса, журналы и числа — примеры исходника, а не результаты тестов ArmSoM.

Редакционные примечания · ArmSoM Docs · Rockchip Linux

Команды исходника показывают общую, используемую и резервируемую память Linux. Технических рисунков нет. Запись sysrq или drop_caches меняет состояние системы: это сохранённые примеры, при подготовке они не выполнялись. x в echo x — заполнитель исходника, а не готовое числовое значение.

SoC исходника Ядро исходника
ARM Linux 4.19

1. Информация об общей памяти

1.1 meminfo

cat /proc/meminfo
MemTotal: 1497696 kB
MemFree: 590524 kB
MemAvailable: 773252 kB
Buffers: 768 kB
Cached: 216892 kB
SwapCached: 14204 kB
Active: 260884 kB
Inactive: 176744 kB
Active(anon): 120620 kB
Inactive(anon): 106688 kB
Active(file): 140264 kB
Inactive(file): 70056 kB
Unevictable: 3224 kB
Mlocked: 3224 kB
SwapTotal: 748844 kB
SwapFree: 346156 kB
Dirty: 776 kB
Writeback: 0 kB
AnonPages: 220804 kB
Mapped: 194276 kB
Shmem: 4968 kB
KReclaimable: 43900 kB
Slab: 111060 kB
SReclaimable: 40648 kB
SUnreclaim: 70412 kB
KernelStack: 18496 kB
PageTables: 42096 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 1497692 kB
Committed_AS: 41751048 kB
VmallocTotal: 263061440 kB
VmallocUsed: 30368 kB
VmallocChunk: 0 kB
Percpu: 2528 kB
CmaTotal: 532480 kB
CmaFree: 0 kB

MemTotal = MemFree + Buffers + Cached

Примечание: это исходное равенство. Приведённые числа ему не удовлетворяют; это не универсальное тождество памяти. Текст не исправлен молча.

SwapTotal/SwapFree: исходник говорит о включении и выделении swap командой swap из системных скриптов. Это имя команды требует проверки в BSP.

Раздел подкачки — специальная область накопителя. При нехватке физической памяти ОС переносит туда временно неиспользуемые данные, освобождая память текущим программам.

Slab показывает текущий объём: освобождаемый SReclaimable и неосвобождаемый SUnreclaim. Чрезмерный рост может указывать на утечку.

Vmalloc: VmallocTotal — общий размер, VmallocUsed — использованный.

CMA: CmaTotal — общий размер, CmaFree — свободный.

Заимствованные системой страницы CMA также считаются занятыми и уменьшают CmaFree.

1.2 sysrq-trigger

echo m > /proc/sysrq-trigger
Mem-Info:
active_anon:43194 inactive_anon:26284 isolated_anon:0
 active_file:35286 inactive_file:17959 isolated_file:0
 unevictable:806 dirty:0 writeback:0 unstable:0
 slab_reclaimable:10164 slab_unreclaimable:17630
 mapped:48836 shmem:1280 pagetables:10550 bounce:0
 free:134653 free_pcp:717 free_cma:0
Node 0 active_anon:172776kB inactive_anon:105136kB active_file:141144kB
inactive_file:71836kB unevictable:3224kB isolated(anon):0kB
isolated(file):0kB mapped:195344kB dirty:0kB writeback:0kB shmeo
DMA32 free:538612kB min:4884kB low:24024kB high:25520kB active_anon:172776kB
inactive_anon:105136kB active_file:141144kB inactive_file:71836kB
unevictable:3224kB writepending:0kB present:2095104kB
lowmem_reserve[]: 0 0 0
DMA32: 13625*4kB (UEH) 12210*8kB (UEH) 8286*16kB (UMEH) 4151*32kB (UMEH)
1157*64kB (UMEH) 223*128kB (UM) 46*256kB (U) 9*512kB (U) 2*1024kB (U)
0*2048kB 0*4096kB = 538612kB
58687 total pagecache pages
3564 pages in swap cache
Swap cache stats: add 155134, delete 151579, find 11930/52536
Free swap = 346412kB
Total swap = 748844kB
523776 pages RAM
0 pages HighMem/MovableOnly
149352 pages reserved
133120 pages cma reserved

2. Информация о памяти ядра

2.1 slab

Для интерфейса отладки выделений ядра включите два макроса конфигурации сборки:

CONFIG_SLUB_SYSFS=y
CONFIG_SLUB_DEBUG=y

Команда вычисления общего размера slab:

echo `cat /proc/slabinfo |awk 'BEGIN{sum=0;}{sum=sum+$3*$4;}END{print sum/1024/1024}'` MB

2.1.1 kernfs_node_cache

Пример исходника показывает 2.5M для kernfs: 655 pages = 2.55859375 MBytes.

[root@RV1126_RV1109:/]# cat /proc/slabinfo |grep kernfs_node_cache
kernfs_node_cache 18319 18340 144 28 1 : tunables 0 0 0 :
slabdata 655 655 0

Код: fs/kernfs/mount.c.

void __init kernfs_init(void)
{

    /*
     * the slab is freed in RCU context, so kernfs_find_and_get_node_by_ino
     * can access the slab lock free. This could introduce stale nodes,
     * please see how kernfs_find_and_get_node_by_ino filters out stale
     * nodes.
     */
    kernfs_node_cache = kmem_cache_create("kernfs_node_cache",
                          sizeof(struct kernfs_node),
                          0,
                          SLAB_PANIC | SLAB_TYPESAFE_BY_RCU,
                          NULL);
}

2.1.2 inode_cache

Исходник указывает 3.2M для inode cache: 816 pages = 3.1875 MBytes. Однако журнал ниже содержит 317 slabs; расхождение сохранено для проверки.

[root@RV1126_RV1109:/]# cat /proc/slabinfo |grep inode_cache
inode_cache 6282 6340 408 20 2 : tunables 0 0 0 :
slabdata 317 317 0

Код: fs/inode.c.

void __init inode_init(void)
{
    /* inode slab cache */
    inode_cachep = kmem_cache_create("inode_cache",
                     sizeof(struct inode),
                     0,
                     (SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|
                     SLAB_MEM_SPREAD|SLAB_ACCOUNT),
                     init_once);
}

2.2 memblock

Интерфейс отладки резервируемой системной памяти: добавьте memblock=debug в bootargs при настройке сборки:

chosen {
    bootargs = "earlycon=uart8250,mmio32,0xff570000 console=ttyFIQ0 memblock=debug";
};
[ 0.000000] MEMBLOCK configuration:
[ 0.000000] memory size = 0x3fdb8000 reserved size = 0x11706eb8
[ 0.000000] memory.cnt = 0x2
[ 0.000000] memory[0x0] [0x00000000-0x083fffff], 0x08400000 bytes flags: 0x0
[ 0.000000] memory[0x1] [0x08648000-0x3fffffff], 0x379b8000 bytes flags: 0x0
[ 0.000000] reserved.cnt = 0x7
[ 0.000000] reserved[0x0] [0x00004000-0x00007fff], 0x00004000 bytes flags: 0x0
[ 0.000000] reserved[0x1] [0x00100000-0x00e32b2f], 0x00d32b30 bytes flags: 0x0
[ 0.000000] reserved[0x2] [0x08000000-0x080fffff], 0x00100000 bytes flags: 0x0
[ 0.000000] reserved[0x3] [0x08300000-0x08318fff], 0x00019000 bytes flags: 0x0
[ 0.000000] reserved[0x4] [0x2dc00000-0x3dbfffff], 0x10000000 bytes flags: 0x0 CMA
[ 0.000000] reserved[0x5] [0x3df00000-0x3dfb7387], 0x000b7388 bytes flags: 0x0
[ 0.000000] reserved[0x6] [0x3f800000-0x3fffffff], 0x00800000 bytes flags: 0x0 CMA

Крупные резервы включают initrd (для загрузки root) и node memmap (для управления страницами).

initrd резервирует 13MBytes:

void __init arm_memblock_init(const struct machine_desc *mdesc)
{
    arm_initrd_init();
}

node memmap резервирует 8MBytes:

[ 0.000000] On node 0 totalpages: 262006
[ 0.000000] memblock_reserve: [0x3ef75000-0x3f774fff]
memblock_virt_alloc_internal+0x108/0x1a4
[ 0.000000] alloc_node_mem_map: node 0, pgdat b0d4bd00, node_mem_map eef75000
[ 0.000000] Normal zone: 2048 pages used for memmap
[ 0.000000] Normal zone: 0 pages reserved
[ 0.000000] Normal zone: 262006 pages, LIFO batch:63

Карта памяти устройства при загрузке:

[ 0.000000] Virtual kernel memory layout:
[ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
[ 0.000000] vmalloc : 0xf0800000 - 0xff800000 ( 240 MB)
[ 0.000000] lowmem : 0xb0000000 - 0xf0000000 (1024 MB)
[ 0.000000] pkmap : 0xafe00000 - 0xb0000000 ( 2 MB)
[ 0.000000] modules : 0xaf000000 - 0xafe00000 ( 14 MB)
[ 0.000000] .text : 0x(ptrval) - 0x(ptrval) (9184 kB)
[ 0.000000] .init : 0x(ptrval) - 0x(ptrval) (1024 kB)
[ 0.000000] .data : 0x(ptrval) - 0x(ptrval) ( 332 kB)
[ 0.000000] .bss : 0x(ptrval) - 0x(ptrval) ( 896 kB)
[ 0.000000] Memory: 752320K/1048024K available (8192K kernel code, 331K rwdata, 1900K rodata, 1024K init, 895K bss, 25368K reserved, 270336K cma-reserved, 0K highmem)

752320K: доступная память свободных страниц, nr_free_pages() << (PAGE_SHIFT - 10).

1048024K: вся видимая физическая память, physpages << (PAGE_SHIFT - 10).

kernel code: код ядра, codesize = _etext - _stext.

rwdata: данные для чтения/записи, datasize = _edata - _sdata.

rodata: данные только для чтения, rosize = __end_rodata - __start_rodata.

init: включает init_data_size = __init_end - __init_begin и init_code_size = _einittext - _sinittext.

bss: неинициализированные глобальные переменные, bss_size = __bss_stop - __bss_start.

reserved: резерв memblock, physpages - totalram_pages - totalcma_pages.

cma-reserved: резерв CMA, totalcma_pages.

[ 0.000000] Reserved memory: created CMA memory pool at 0x3f800000, size 8 MiB
[ 0.000000] OF: reserved mem: initialized node linux,cma, compatible id shared-dma-pool
[ 0.000000] Reserved memory: created CMA memory pool at 0x2dc00000, size 256 MiB
[ 0.000000] OF: reserved mem: initialized node isp, compatible id shared-dma-pool

2.2.1 memory

Ядро поддерживает несколько блоков памяти. До входа в ядро часть памяти Rockchip используется специально: например, код OPTEE/ATF размещается в 132M–135M. В исходном примере блок размером 0x248000 хранит код OPTEE.

[root@RV1126_RV1109:/]# cat /sys/kernel/debug/memblock/memory
   0: 0x00000000..0x083fffff
   1: 0x08648000..0x3fffffff

2.2.2 reserved

[root@RV1126_RV1109:/]# cat /sys/kernel/debug/memblock/reserved
   0: 0x00004000..0x00007fff
   1: 0x00100000..0x00e32b2f
   2: 0x08000000..0x080fffff
   3: 0x08300000..0x08318fff
   4: 0x083ff000..0x083fffff
   5: 0x2dc00000..0x3dbfffff
   6: 0x3df00000..0x3dfb7387
   7: 0x3ee41000..0x3ef3cfff
   8: 0x3ef3f480..0x3ef3f4f7
   9: 0x3ef3f500..0x3ef3f803
  10: 0x3ef3f834..0x3f7fefff
  11: 0x3f7ff040..0x3f7ff384
  12: 0x3f7ff3c0..0x3f7ff3fb
  13: 0x3f7ff400..0x3f7ff583
  14: 0x3f7ff5c0..0x3f7ff784
  15: 0x3f7ff7c0..0x3f7ff837
  16: 0x3f7ff840..0x3f7ff84f
  17: 0x3f7ff880..0x3f7ff88f
  18: 0x3f7ff8c0..0x3f7ff8c3
  19: 0x3f7ff900..0x3f7ff903
  20: 0x3f7ff940..0x3f7ffa4b
  21: 0x3f7ffa80..0x3f7ffb8b
  22: 0x3f7ffbc0..0x3f7ffccb
  23: 0x3f7ffcf0..0x3f7ffd08
  24: 0x3f7ffd0c..0x3f7ffd24
  25: 0x3f7ffd28..0x3f7ffd72
  26: 0x3f7ffd74..0x3f7ffd8e
  27: 0x3f7ffd90..0x3f7ffdaa
  28: 0x3f7ffdac..0x3f7ffdc6
  29: 0x3f7ffdc8..0x3f7ffde2
  30: 0x3f7ffde4..0x3f7ffdfe
  31: 0x3f7ffe00..0x3f7ffedf
  32: 0x3f7ffee8..0x3f7fff9f
  33: 0x3f7fffb0..0x3fffffff

2.3 zoneinfo

cat /proc/zoneinfo
Node 0, zone DMA32
  per-node stats
      nr_inactive_anon 28250
      nr_active_anon 34245
      nr_inactive_file 29724
      nr_active_file 33943
      nr_unevictable 806
      nr_slab_reclaimable 10088
      nr_slab_unreclaimable 17495
      nr_isolated_anon 0
    nr_isolated_file 0
    workingset_refault 258089
    workingset_activate 54883
    workingset_restore 35120
    workingset_nodereclaim 4574
    nr_anon_pages 59384
    nr_mapped 65408
    nr_file_pages 70824
    nr_dirty 31
    nr_writeback 0
    nr_writeback_temp 0
    nr_shmem 1581
    nr_shmem_hugepages 0
    nr_shmem_pmdmapped 0
    nr_anon_transparent_hugepages 0
    nr_unstable 0
    nr_vmscan_write 148946
    nr_vmscan_immediate_reclaim 2540
    nr_dirtied 798484
    nr_written 938957
    nr_kernel_misc_reclaimable 0
    nr_unreclaimable_pages 0
    nr_ion_heap 0
    nr_ion_heap_pool 0
    nr_gpu_heap 0
pages free 133183
      min 1221
      low 6006
      high 6380
      spanned 523776
      present 523776
      managed 374424
      protection: (0, 0, 0)
    nr_free_pages 133183
    nr_zone_inactive_anon 28250
    nr_zone_active_anon 34245
    nr_zone_inactive_file 29724
    nr_zone_active_file 33943
    nr_zone_unevictable 806
    nr_zone_write_pending 31
    nr_mlock 806
    nr_page_table_pages 10425
    nr_kernel_stack 18256
    nr_bounce 0
    nr_zspages 26061
    nr_free_cma 0
pagesets
  cpu: 0
            count: 342
            high: 378
            batch: 63
vm stats threshold: 30
  cpu: 1
            count: 301
            high: 378
            batch: 63
  vm stats threshold: 30
    cpu: 2
              count: 32
              high: 378
              batch: 63
  vm stats threshold: 30
    cpu: 3
              count: 296
              high: 378
              batch: 63
  vm stats threshold: 30
  node_unreclaimable: 0
  start_pfn: 512
Node 0, zone Normal
  pages free 0
        min 0
        low 0
        high 0
        spanned 0
        present 0
        managed 0
        protection: (0, 0, 0)
Node 0, zone Movable
  pages free 0
        min 0
        low 0
        high 0
        spanned 0
        present 0
        managed 0
        protection: (0, 0, 0)

3. Свободная память

3.1 free

total: общий объём памяти под управлением страниц ядра.

used: используемая память.

free: свободная память.

shared: общая память; исходник приводит анонимные страницы как пример.

buffers: буферная память.

cached: кэшированная память.

Исходник различает cached и buffers так: cached ускоряет чтение, сохраняя уже прочитанные данные в памяти и избегая повторного обращения к диску. Buffers ускоряет запись: разрозненные операции собираются в памяти и затем записываются партиями, уменьшая фрагментацию диска и повторный поиск. Это упрощённое объяснение исходника, а не полное описание кэширования современного Linux.

free
                  total used free shared buffers
  Mem: 1533640704 1308901376 224739328 6422528 921600
-/+ buffers/cache: 1307979776 225660928
  Swap: 766816256 401342464 365473792
free -m
                  total used free shared buffers
  Mem: 1462 1249 213 6 0
-/+ buffers/cache: 1248 214
  Swap: 731 382 348
free -h
                total used free shared buffers
Mem: 1.4G 1.2G 212M 6.1M 900K
-/+ buffers/cache: 1.2G 213M
Swap: 731M 383M 349M

4. Очистка кэшей

4.1 drop_caches

echo x > /proc/sys/vm/drop_caches

Очистить pagecache:

echo 1 > /proc/sys/vm/drop_caches

Очистить dentries и inodes:

echo 2 > /proc/sys/vm/drop_caches

Очистить перечисленные кэши (pagecache, dentries и inodes):

echo 3 > /proc/sys/vm/drop_caches

5. Использование виртуальной памяти

5.1 vmallocinfo

cat /proc/vmallocinfo
0x0000000000000000-0x0000000000000000 8192 bpf_jit_binary_alloc+0x70/0x110
pages=1 vmalloc
...
0x0000000000000000-0x0000000000000000 20480 start_kernel+0x330/0x4f0
pages=4 vmalloc
0x0000000000000000-0x0000000000000000 8192 of_iomap+0x4c/0xb8
phys=0x00000000fdd00000 ioremap
0x0000000000000000-0x0000000000000000 20480 start_kernel+0x330/0x4f0
pages=4 vmalloc
0x0000000000000000-0x0000000000000000 8192 of_iomap+0x4c/0xb8
phys=0x00000000fdd20000 ioremap
0x0000000000000000-0x0000000000000000 20480 start_kernel+0x330/0x4f0
pages=4 vmalloc

5.2 vmstat

cat /proc/vmstat

6. Давление памяти

6.1 pressure

cat /proc/pressure/memory

VSS — Virtual Set Size: виртуальная память, включая общие библиотеки.

RSS — Resident Set Size: физическая память, включая общие библиотеки.

PSS — Proportional Set Size: физическая память с пропорциональным учётом общих библиотек.

USS — Unique Set Size: физическая память исключительно процесса, без общих библиотек.

Обычное соотношение по исходнику: VSS >= RSS >= PSS >= USS.

Другие статьи по теме → · Учебные маршруты →