SLUB: Unable to allocate memory — Решение нехватки памяти SLUB в Linux
Архитектура ошибки и симптомы сбоя
Критический сбой аллокатора «SLUB: Unable to allocate memory from slab cache (gfp_flags=...)» генерируется подсистемой ядра SLUB Allocator. Ошибка означает, что аллокатор ядра не смог выделить физические страницы (Page Frames) из базового аллокатора страниц Buddy Allocator для создания или расширения кэша структур фиксированного размера (kmalloc-512, dentry, inode_cache, skbuff_head_cache). В результате системные вызовы ядра аварийно завершаются с ошибкой -ENOMEM, а сервер переходит в режим паники или зависания.
Диагностическая таблица параметров сбоя
| Параметр | Значение | Инженерный смысл сбоя |
|---|---|---|
| SLUB Allocator | Kernel Object Allocator | Высокопроизводительный аллокатор структур данных ядра Linux по умолчанию. |
| gfp_flags (GFP_ATOMIC) | Get Free Page Flags | Флаги контекста: GFP_ATOMIC запрещает переход потока в сон для сброса страниц. |
| Order Allocation | 2^Order Pages | Количество последовательных смежных физических страниц памяти, запрошенных аллокатором. |
Пошаговое дерево решений и сценарии траблшутинга
Сценарий 1: Экспресс-анализ фрагментации физических страниц памяти
Проверьте доступность крупных непрерывных блоков памяти по зонам (Buddy Allocator):
# Анализ фрагментации оперативной памяти по порядкам (Order 0..10):
cat /proc/buddyinfo
# Если в старших порядках (Order 3–10) стоят нули, память сильно фрагментирована!Сценарий 2: Экстренное принудительное уплотнение (дефрагментация) памяти
# Запуск компактификации физической памяти:
echo 1 | sudo tee /proc/sys/vm/compact_memory
# Сброс неиспользуемых кэшей dentries и inodes:
echo 3 | sudo tee /proc/sys/vm/drop_cachesСценарий 3: Увеличение аварийного резерва свободной памяти ядра (min_free_kbytes)
Увеличьте пул неприкосновенного запаса памяти, доступного для атомарных аллокаций ядра (GFP_ATOMIC):
# Внесите настройки в /etc/sysctl.d/99-slub-mem.conf (пример для серверов 32-128GB RAM):
cat <<EOF | sudo tee /etc/sysctl.d/99-slub-mem.conf
# Выделение 2GB под аварийный резерв ядра:
vm.min_free_kbytes = 2097152
# Повышение агрессивности компактификации памяти:
vm.compaction_proactiveness = 60
# Отключение изоляции зон NUMA:
vm.zone_reclaim_mode = 0
# Настройка порога начала фонового сброса dirty страниц:
vm.dirty_background_ratio = 5
vm.dirty_ratio = 10
EOF
sudo sysctl -p /etc/sysctl.d/99-slub-mem.confITSTM настроит параметры NUMA-балансировки, проактивную компактификацию памяти и профили HugePages для исключения фрагментации ядра.
Частые вопросы (FAQ)
Почему ошибка SLUB возникает даже тогда, когда утилита free показывает много свободной памяти?
Свободная память может присутствовать в виде разрозненных страниц по 4KB (Order 0). Если драйверу требуется непрерывный физический блок памяти размером 64KB (Order 4) для DMA-дескрипторов, а непрерывных страниц нет, аллокатор завершится ошибкой ENOMEM.
Что означает флаг GFP_ATOMIC при вызове kmalloc?
Флаг GFP_ATOMIC означает, что запрос выполняется из контекста аппаратного прерывания или спинлока (Interrupt Context), где ядро не имеет права засыпать, сбрасывать данные на диск или вызывать OOM Killer для освобождения памяти.
Чем SLUB отличается от классического SLAB и SLOB?
SLAB — старый аллокатор со сложными очередями дескрипторов. SLUB — современный стандарт ядра Linux без очередей очередей объектов, оптимизированный под многоядерные архитектуры NUMA. SLOB — минималистичный аллокатор для встраиваемых систем с объемом RAM в несколько мегабайт.
Как просмотреть параметры конкретного SLUB кэша через sysfs?
Используйте каталог /sys/kernel/slab/. Например: cat /sys/kernel/slab/kmalloc-512/objects.