Память ядра и slab: slabtop и куда уходит RAM

Рейтинг: 45.3% · 9 голосов
Подробный курс по диагностике и производительности Linux для админов и DevOps: с чего начать, методология USE, логи (journalctl, dmesg), процессы, CPU, память и OOM, диск и IO (iostat), сеть (ss, tcpdump), системные вызовы и strace, ltrace, perf, флеймграфы, ftrace, eBPF и bpftrace, lsof, мониторинг. Разбор каждого инструмента с чтением вывода.
Ответить
Аватара пользователя
Dmitry_SRE
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Память ядра и slab: slabtop и куда уходит RAM

Сообщение Dmitry_SRE »

Оглавление курса (47)
  1. С чего начать диагностику Linux: методология вместо паники
  2. Первые 60 секунд: экспресс-диагностика нагруженного сервера
  3. Методологии диагностики: USE, RED и здравый смысл
  4. Логи systemd через journalctl: где искать причину
  5. Где лежат логи Linux: /var/log, dmesg и rsyslog
  6. Источники правды: load average, /proc и /sys
  7. Процессы Linux: ps, pstree и состояния процессов
  8. Интерактивный мониторинг: top и htop
  9. Метрики процессов во времени: pidstat
  10. Приоритеты и ограничения: nice, ionice, cgroups
  11. Сигналы и зависшие процессы: kill, и что делать с D-state
  12. Загрузка CPU: user, system, iowait, steal и контекст-свитчи
  13. Диагностика CPU по ядрам: vmstat и mpstat
  14. Профилирование CPU: perf top и поиск пожирателя
  15. Частоты, троттлинг и NUMA: turbostat и numastat
  16. Память Linux: RSS, VSZ, page cache и миф о нехватке памяти
  17. Сколько памяти занято: free, /proc/meminfo и vmstat
  18. Поиск утечек и пожирателей памяти: smem, pmap, smaps
  19. Swap и подкачка: swapon, swappiness, когда своп - это боль
  20. OOM killer: кто и за что убил процесс
  21. Память ядра и slab: slabtop и куда уходит RAM (вы здесь)
  22. Подсистема ввода-вывода: путь запроса от приложения до диска
  23. Диагностика диска: iostat и чтение await, %util
  24. Кто грузит диск: iotop и атрибуция io процессам
  25. Файловые системы: df, du, иноды и куда делось место
  26. Глубокая диагностика блочного слоя: blktrace и biolatency
  27. Кеш страниц и грязные данные: dirty pages, fsync, drop_caches
  28. Сетевой стек Linux: путь пакета и где возникают задержки
  29. Сокеты и соединения: ss и netstat
  30. Захват трафика: tcpdump для диагностики сети
  31. Задержки и потери в сети: ping, mtr, диагностика латентности
  32. Сеть как источник проблем: nftables, conntrack, дропы
  33. Что такое системный вызов и зачем его трассировать
  34. strace: трассировка системных вызовов на практике
  35. strace в бою: почему программа висит, падает или тормозит
  36. ltrace: трассировка вызовов библиотек
  37. Накладные расходы трассировки и безопасные альтернативы
  38. perf: универсальный профайлер Linux
  39. Флеймграфы: визуализация профиля производительности
  40. Трассировка ядра: ftrace и trace-cmd
  41. eBPF: революция в наблюдаемости Linux
  42. Инструменты eBPF на практике: BCC и bpftrace
  43. lsof: открытые файлы, дескрипторы, кто держит файл и порт
  44. Разбор кейса: приложение тормозит - пошаговая диагностика
  45. Непрерывный мониторинг: sar, node_exporter, Grafana, Zabbix
  46. Диагностика в контейнерах: cgroups, лимиты, Docker и Kubernetes
  47. Карта инструментов и сквозной разбор инцидента производительности
Когда RAM съело не приложение, а само ядро

Классическая ситуация. Заходишь на сервер, смотришь free -h, видишь, что свободной памяти почти нет. Открываешь top (или htop), сортируешь по RES - а там пусто, ни одного жирного процесса. Сумма по всем приложениям едва набирает половину занятого. Память есть, а кто её держит - непонятно. Вот тут новичок обычно зависает: начинает паниковать или сразу ребутить машину.

Не спеши. Очень часто память забирает не пользовательский процесс, а само ядро Linux - точнее, его внутренние кеши. И живут они в области, которую top вообще не показывает, потому что у ядра нет "процесса" в привычном смысле: нет PID, нет строки в списке задач. Это и есть тема урока: как устроена память ядра linux, что такое slab, и как с помощью утилиты slabtop за минуту понять, куда утекла RAM.

Сначала прикинь на пальцах, виновато ли вообще ядро. У free -h есть колонки used, free, buff/cache и available. Если used маленький, а буквально вся RAM в buff/cache - это, скорее всего, обычный кеш файлов (page cache), и available покажет, что памяти на самом деле полно. А вот если used большой, но в top нет соответствующих процессов - тогда копаем в ядро.

Этот навык нужен, когда: free показывает мало свободной памяти, а виновного процесса нет; когда сервер с кучей мелких файлов (почтовик в формате maildir, кеш веб-сервера, node_modules, миллионы временных файлов) начинает тормозить; когда после тяжёлого du, find или rsync по гигантскому дереву память будто прилипла. Разберёмся по шагам.

Изображение

Что такое slab linux и зачем ядру свои кеши

Ядру постоянно нужны мелкие объекты одинакового размера: структура на каждый открытый файл, на каждый элемент пути в файловой системе, на каждый блок диска в памяти, на каждый сетевой сокет. Если под каждую такую структуру дёргать общий аллокатор страниц (страница - это 4 КБ на x86-64), получится дико расточительно и медленно: объект-то занимает 200 байт, а страница 4096. Девяносто пять процентов в мусор.

Чтобы не плодить отходы, в ядре есть slab-аллокатор. Идея простая, как лоток для яиц. Ядро берёт у системы несколько страниц подряд (это и есть "slab", плита) и нарезает их на одинаковые ячейки под объекты одного типа. Когда объект освобождается, ячейка не возвращается системе сразу, а остаётся в кеше - наготове под следующий такой же объект. Получаем пул заранее нарезанных ячеек: выделить и освободить почти мгновенно, без обращения к глобальному аллокатору и без блокировок на горячем пути.

Важно на 2026 год. Исторически в ядре было три аллокатора: SLAB, SLUB и SLOB. К нашему времени осталась только реализация SLUB: SLOB убрали в ядре 6.4, а старый SLAB пометили устаревшим в 6.5 и полностью вырезали в 6.8. Так что на любом современном дистрибутиве (ядро 6.x) под капотом именно SLUB. Для нас как для диагностов это почти ничего не меняет: те же кеши, тот же slabtop, тот же /proc/slabinfo. Меняются мелочи под капотом и набор отладочных ручек в /sys/kernel/slab. Имя "slab" как общий термин для технологии при этом осталось - не путай технологию (slab) и одну из её реализаций (SLAB, которой больше нет).

Каждый тип объекта живёт в своём именованном кеше. Главные, которые ты будешь встречать чаще всего:
  • dentry - directory entry, кеш элементов путей. Каждый компонент пути (каждое имя файла или каталога, которое ядро трогало) оседает тут.
  • inode_cache и ext4_inode_cache (или xfs_inode, btrfs_inode и т.п.) - кеш inode, метаданных файлов: размер, права, владелец, временные метки.
  • buffer_head - служебные структуры для блоков блочного устройства.
  • kmalloc-* - семейство кешей общего назначения под произвольные аллокации ядра (kmalloc-64, kmalloc-256, kmalloc-1k и т.д., размер в имени).
  • TCP, sock_inode_cache, kmalloc-cg-* - сетевые структуры и аллокации, учтённые на cgroup (с cgroup v2 это норма по умолчанию).
Важная развилка - память slab делится на два сорта, и это видно в /proc/meminfo:
  • SReclaimable - то, что ядро может отдать обратно под давлением памяти. Сюда входят dentry и inode-кеши. Это по сути не "потеря" памяти, а полезный кеш: понадобится RAM приложению - ядро сожмёт эти кеши само, через механизм shrinker.
  • SUnreclaim - то, что освободить нельзя, пока объекты реально используются. Если эта цифра неуклонно растёт днями и неделями при стабильной нагрузке - вот это уже повод заподозрить утечку в ядре или драйвере.
Практика: slabtop и /proc/slabinfo - читаем вывод по колонкам

Первый инструмент - slabtop из пакета procps-ng. Это как top, только не для процессов, а для slab-кешей ядра в реальном времени. Запускаем с правами root:

Код: Выделить всё

sudo slabtop -s c
Флаг -s c сортирует по размеру кеша (cache size), то есть самые жирные кеши окажутся сверху - именно то, что нам нужно для поиска "пожирателя". Полезно знать и другие ключи сортировки: -s o - по числу объектов (это поведение по умолчанию), -s a - по активным объектам, -s s - по размеру объекта. Букву сортировки можно менять прямо в работающем slabtop, нажимая соответствующую клавишу. Для разового снимка без интерактива удобен -o (once - вывести один раз и выйти). Примерный вывод:

Код: Выделить всё

 Active / Total Objects (% used)    : 3120450 / 3340120 (93.4%)
 Active / Total Slabs (% used)      : 84210 / 84210 (100.0%)
 Active / Total Caches (% used)     : 142 / 198 (71.7%)
 Active / Total Size (% used)       : 980320.50K / 1042880.00K (94.0%)
 Minimum / Average / Maximum Object : 0.01K / 0.31K / 16.00K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
1820000 1798200  98%    0.19K  43333       42    346664K dentry
 640050  638900  99%    0.58K  23700       27    379200K ext4_inode_cache
 210400  208100  98%    0.10K   5400       40     21600K buffer_head
 ...
Разбираем шапку и колонки по полям - это и есть самое важное для новичка:
  • NAME - имя кеша. Видишь сверху dentry и ext4_inode_cache - значит, память съели кеши файловой системы.
  • OBJS - всего объектов в кеше (и занятых, и пустых наготове).
  • ACTIVE - сколько из них реально используется прямо сейчас.
  • USE - процент использования, ACTIVE делить на OBJS. Если у dentry 98% - кеш плотно занят, мало "холодных" пустых ячеек.
  • OBJ SIZE - размер одного объекта. У dentry это около 0.19K, мелочь. Но умножь на полтора миллиона штук - и набегают сотни мегабайт.
  • SLABS - сколько "плит" (групп страниц) ушло под этот кеш.
  • OBJ/SLAB - сколько объектов влезает в одну плиту.
  • CACHE SIZE - итоговый размер кеша. Вот по нему мы и сортировали через -s c. Здесь dentry держит около 346 МБ, а inode-кеш около 379 МБ. Сложили - больше 700 МБ только на метаданных файлов.
Шапка тоже полезна. Строка Active / Total Size даёт суммарный объём по всем кешам (тут около 1 ГБ), а Maximum Object подсказывает, нет ли аномально жирных объектов. Низкий общий процент used (объекты есть, но почти не активны) намекает на фрагментацию: кеш раздут пустыми ячейками.

Под капотом slabtop читает текстовый файл /proc/slabinfo. Можно глянуть и его напрямую (тоже от root):

Код: Выделить всё

sudo head -3 /proc/slabinfo
slabinfo - version: 2.1
# name            <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : ...
dentry            1820000 1820000    192   42    2 : ...
Поля: active_objs (используется сейчас), num_objs (всего выделено), objsize (размер объекта в байтах), objperslab (объектов на плиту), pagesperslab (страниц на плиту). Это ровно то, что slabtop раскладывает в красивую таблицу. Удобный однострочник для топа без интерактива:

Код: Выделить всё

sudo sort -k2 -rn /proc/slabinfo | head -5
Чтобы увидеть общую картину памяти ядра, смотрим /proc/meminfo - тут root уже не нужен:

Код: Выделить всё

grep -E "Slab|SReclaimable|SUnreclaim|KernelStack|PageTables" /proc/meminfo
Slab:            1042880 kB
SReclaimable:     742300 kB
SUnreclaim:       300580 kB
KernelStack:       18432 kB
PageTables:        96420 kB
Как читать:
  • Slab - суммарно всё, что забрал slab-аллокатор. Тут гигабайт. Это та память, которую top не показывал. Slab = SReclaimable + SUnreclaim.
  • SReclaimable большой (742 МБ) - в основном dentry/inode. Это нормальный кеш, ядро отдаст его под нагрузкой. Паниковать не нужно. Кстати, именно SReclaimable учитывается в available памяти free, поэтому available может быть большим даже при огромном Slab.
  • SUnreclaim - реально занятые ядром структуры. Норма зависит от железа и нагрузки, но резкий или линейный неконтролируемый рост этой цифры - тревога.
  • KernelStack - память под стеки ядра, по одному на каждый поток (на x86-64 обычно 16 КБ на поток). Если она огромная - у тебя где-то форк-бомба или взрывное число тредов.
  • PageTables - таблицы трансляции адресов. Раздувается у процессов с гигантскими картами памяти (большие БД, много shared-памяти, без HugePages).
Сброс кешей через drop caches - осторожно, это диагностика, не лечение

Допустим, ты увидел гору в dentry/inode и хочешь проверить: это правда отдаваемый кеш или настоящая утечка? Есть ручка drop_caches. Она просит ядро отпустить чистые (не грязные) кеши. Значения такие:
  • 1 - сбросить только page cache (кеш содержимого файлов).
  • 2 - сбросить reclaimable slab, то есть dentry и inode-кеши.
  • 3 - и то, и другое.
Сначала сбрасываем на диск грязные данные через sync (иначе несохранённое просто не отдадут), потом пишем в ручку:

Код: Выделить всё

sync
echo 2 | sudo tee /proc/sys/vm/drop_caches
Теперь снова посмотри slabtop и meminfo. Если SReclaimable резко упал и dentry схлопнулся - всё в порядке, это был обычный кеш, память была не потеряна. Если же цифры почти не сдвинулись - объекты реально заняты, и это уже разговор про утечку или просто про честную нагрузку (например, реально открыты миллионы файлов).

Очень важное предупреждение. drop_caches - это инструмент диагностики и тестов, а не средство "ускорить сервер". В интернете полно советов пихать его в cron - это вредный карго-культ. Ты выкидываешь полезный горячий кеш, и ядру придётся заново читать всё с диска: будет всплеск дисковых операций и просадка по latency сразу после сброса. На бою регулярно так делать не надо. Если dentry-кеш действительно мешает, правильнее тюнить vm.vfs_cache_pressure (повышение значения заставляет ядро агрессивнее освобождать dentry/inode), а не дёргать drop_caches по таймеру.

Уровень повыше: eBPF против утечек ядра (актуально на 2026)

slabtop отвечает на вопрос "сколько и в каком кеше", но не отвечает "кто это аллоцировал". Раньше тут начинались пляски с ftrace и kmemleak. Сегодня (2026) зрелый eBPF снимает вопрос почти полностью, и это уже стандарт диагностики, а не экзотика.
  • slabratetop (из пакета bcc, в Debian/Ubuntu - bpfcc-tools) показывает скорость аллокаций по кешам в стиле top: какой кеш прямо сейчас активнее всего набивается. Если SUnreclaim растёт - запускаешь slabratetop и видишь, кто лидер по байтам в секунду.
  • memleak (тоже bcc) - главный инструмент против утечек. Он инструментирует kmalloc/kfree, kmem_cache_alloc/kmem_cache_free и страничные аллокации, копит стеки вызовов и показывает те, что аллоцировали, но не освободили. То есть выдаёт прямо стек ядра, ведущий к утечке.

Код: Выделить всё

sudo slabratetop
sudo memleak -p $(pgrep -n myapp)
sudo memleak --kernel-threads-only 5
Под капотом memleak опирается на kmem-трейспоинты ядра. Их можно дёрнуть и напрямую через bpftrace, если хочется быстрый однострочник без установки bcc-набора:

Код: Выделить всё

sudo bpftrace -e 'tracepoint:kmem:kmalloc { @bytes[kstack] = sum(args->bytes_alloc); }'
У трейспоинтов kmem:kmalloc и kmem:kmem_cache_alloc есть поля call_site (откуда в ядре пришёл вызов), bytes_req (сколько запросили), bytes_alloc (сколько реально выделили - разница это и есть внутренняя фрагментация) и gfp_flags. Сгруппировав по kstack, ты получишь карту "какой код ядра жжёт память". Связка простая: slabtop говорит ЧТО раздулось, slabratetop - насколько быстро, а memleak/bpftrace - КТО виноват. Этого хватает, чтобы дойти до конкретного драйвера или подсистемы.

Типичные грабли и заблуждения
  • "Память кончается - надо срочно чистить кеши." Нет. SReclaimable - это не утечка, ядро само освободит его, когда понадобится. Заполненный кеш - признак здоровой системы, а не больной. Смотри на available в free, а не на free.
  • Запуск slabtop без sudo. /proc/slabinfo читается только root (права 0400 - это защита от утечки информации о раскладке памяти ядра, ввели как меру против эксплойтов). Без sudo получишь Permission denied или пустоту. Всегда sudo slabtop.
  • Раздутый dentry после du/find/rsync по огромному дереву. Прошёлся по миллионам мелких файлов - ядро закешировало все элементы путей и inode. Это ожидаемо и отдаётся обратно. Не баг.
  • Путать page cache и slab. Page cache (Cached в meminfo) - это содержимое файлов. Slab - это служебные структуры ядра. Разные вещи, разные значения drop_caches (1 против 2).
  • Сразу кричать "утечка в ядре". Реальные утечки ядра/драйверов бывают, но редко. Признак - именно SUnreclaim или конкретный kmalloc-кеш, который растёт линейно во времени и НЕ сбрасывается через drop_caches 3. Сначала исключи нормальный кеш, потом запускай memleak, и только потом думай на драйвер.
  • Искать аллокатор SLAB в /sys. На ядрах 6.8 и новее его нет, остался только SLUB. Старые гайды, где упоминается CONFIG_SLAB или /proc/slabinfo "в формате SLAB", частично устарели - формат полей при этом совместим.
Региональная пометка: на отечественных Astra Linux и RED OS ядро тоже на SLUB, slabtop и /proc/slabinfo работают точно так же - инструменты из пакета procps-ng стандартные. bcc и bpftrace там тоже есть в репозиториях, но версия ядра может быть постарше - проверь, что трейспоинты kmem доступны (ядро 4.9+ для базового eBPF, 5.x+ для комфортной работы).

Мини-лаба: сделай руками прямо сейчас
  • Посмотри стартовое состояние: grep -E "Slab|SReclaimable|SUnreclaim" /proc/meminfo - запиши цифры.
  • Прогрей dentry/inode-кеш: создай дерево из кучи мелких файлов и пройди по нему. Например: mkdir -p /tmp/slablab && for i in $(seq 1 50000); do touch /tmp/slablab/f$i; done, потом find /tmp/slablab -type f | wc -l и du -sh /tmp/slablab.
  • Запусти sudo slabtop -s c -o и найди dentry с inode-кешем в топе. Посмотри, как выросли OBJS и CACHE SIZE.
  • Сбрось reclaimable slab: sync && echo 2 | sudo tee /proc/sys/vm/drop_caches. Снова глянь meminfo - SReclaimable должен заметно упасть.
  • Если стоит bcc: в одном терминале запусти sudo slabratetop, в другом снова прогони цикл с touch - увидишь всплеск аллокаций в dentry/inode-кешах в реальном времени.
  • Убери за собой: rm -rf /tmp/slablab.
Контрольные вопросы
  • free показывает мало свободной памяти, но в top нет жирных процессов. Какой первой командой проверишь, не ядро ли держит RAM, и по какой колонке (и каким флагом) отсортируешь slabtop?
  • Чем SReclaimable отличается от SUnreclaim в /proc/meminfo и какая из этих цифр при бесконтрольном линейном росте намекает на утечку в ядре?
  • Что произойдёт при echo 3 в drop_caches на нагруженном проде и почему нельзя ставить это в cron? Что тюнить вместо этого?
  • slabtop показал, что раздут конкретный kmalloc-кеш, drop_caches не помогает. Каким инструментом 2026 года найдёшь стек ядра, который аллоцировал и не освободил память?
Что запомнить

Если память занята, а виновного процесса нет - подозревай ядро. Открывай sudo slabtop -s c и смотри топ кешей: чаще всего наверху dentry и inode_cache, особенно на машинах с морем мелких файлов. Сверяйся с Slab / SReclaimable / SUnreclaim в /proc/meminfo: reclaimable - это здоровый кеш, ядро отдаст его само, он же учтён в available. drop_caches держи только для диагностики, и то аккуратно; для постоянной настройки есть vm.vfs_cache_pressure. А вот линейно растущий SUnreclaim, который не сбрасывается - редкий, но настоящий повод копать: запускай memleak или slabratetop из bcc и иди по стеку до конкретного драйвера или подсистемы ядра.
👍3 ❤️3 🔥2 😄 🤔
Аватара пользователя
Pdcreate
Сообщения: 1
Зарегистрирован: 11 май 2026, 17:21

Re: Память ядра и slab: slabtop и куда уходит RAM

Сообщение Pdcreate »

Спасибо, наконец понял почему free пугает - у меня на почтовике как раз dentry под гигабайт, оказалось это нормальный reclaimable кеш а не утечка. И available большой, просто я смотрел не туда. Перестал паниковать.
👍1 ❤️2 🔥 😄 🤔
Аватара пользователя
archninja
Сообщения: 1
Зарегистрирован: 14 май 2026, 11:56

Re: Память ядра и slab: slabtop и куда уходит RAM

Сообщение archninja »

А я не знал что SLAB вообще выпилили в 6.8 и теперь только SLUB. Запустил memleak из bcc на тестовом дрвайвере - реально показывает стек где kmalloc без kfree, огонь. Раньше бы с kmemleak неделю мучился.
👍1 ❤️1 🔥1 😄 🤔
Ответить
← Предыдущая глава
OOM killer: кто и за что убил процесс
Следующая глава →
Подсистема ввода-вывода: путь запроса от приложения до диска

Все главы курса «Диагностика и производительность Linux: логи, strace, perf и eBPF»

Поделиться темой: ✈ Telegram VK
Похожие запросы: как посмотреть сколько памяти занято в linuxhtop и top как читать и в чем разницаoom killer кто убил процесс linux как узнатькак понять что съедает память на сервере linux

Вернуться в «Диагностика и производительность Linux: логи, strace, perf и eBPF»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость