Привет! Когда речь заходит о динамическом управлении памятью в Linux, мы имеем дело с несколькими разными подходами, каждый из которых имеет свои плюсы и минусы.
В этой статье разберем три аллокатора памяти ядра: SLAB, SLOB, а также SLUB.
struct kmem_cache {
unsigned int object_size; // Размер объекта
unsigned int num; // Количество объектов в slab'е
struct list_head slabs_full, slabs_partial, slabs_empty; // Списки slab'ов
};
SLAB использует три списка:
struct kmem_cache *my_cache;
my_cache = kmem_cache_create("my_cache", sizeof(struct my_struct), 0, SLAB_HWCACHE_ALIGN, NULL);
void *obj = kmem_cache_alloc(my_cache, GFP_KERNEL);
// используем объект
kmem_cache_free(my_cache, obj); // возвращаем его в кэш
SLAB хорошо подходит для серверных систем с большим количеством параллельных запросов.
void *data = slob_alloc(128);
if (data) {
// Работаем с выделенной памятью
slob_free(data); // Освобождаем память
}
SLOB выделяет блок, минимально необходимый для объекта
Каждый процессор имеет свой собственный активный slab, что оптимизирует работу многопроцессорных систем и минимизирует задержки при выделении памяти.
Пример структуры в SLUB:
struct kmem_cache_cpu {
void **freelist; // Список свободных блоков памяти
struct page *page; // Текущая страница slab'а
};
В этом примере freelist — это указатель на свободные блоки памяти, которые могут быть быстро выделены для новых объектов. Вместо создания сложных кэшей, как в SLAB, SLUB просто хранит указатели на свободные объекты прямо в slab'ах.
В этой статье разберем три аллокатора памяти ядра: SLAB, SLOB, а также SLUB.
Зачем вообще нужны slab-менеджеры?
Ядро Linux работает с множеством объектов, которые занимают память, но их размер может сильно варьироваться. Выделение памяти через обычный механизм работы с кучей (как malloc в юзер пространстве) было бы слишком затратным и приводило бы к значительной фрагментации. Slab‑менеджеры были разработаны для лучшего управления памятью, минимизации фрагментации и ускорения работы с мелкими объектами, которые часто создаются и уничтожаются ядром.Основная идея: slab как контейнер
SLAB основан на концепции кэшей, в которых хранятся объекты определенного размера. Эти объекты размещаются в блоках памяти, которые называются slabами. Каждый slab содержит несколько объектов одного типа и может находиться в одном из трёх состояний:- Пустой (empty) — все объекты свободны.
- Частично заполненный (partial) — некоторые объекты заняты.
- Полностью заполненный (full) — все объекты заняты.
Структура slab'а
Каждый slab состоит из нескольких страниц памяти (по дефолту 4 КБ), которые делятся на маленькие кусочки (объекты). Когда объект освобождается, он не удаляется физически, а возвращается в slab, чтобы его можно было использовать повторно. Это снижает накладные расходы на выделение и освобождение памяти.struct kmem_cache {
unsigned int object_size; // Размер объекта
unsigned int num; // Количество объектов в slab'е
struct list_head slabs_full, slabs_partial, slabs_empty; // Списки slab'ов
};
SLAB использует три списка:
- slabs_full — все объекты в этих slab'ах заняты.
- slabs_partial — slab'ы, в которых есть свободные объекты.
- slabs_empty — пустые slab'ы, которые можно использовать для новых объектов.
struct kmem_cache *my_cache;
my_cache = kmem_cache_create("my_cache", sizeof(struct my_struct), 0, SLAB_HWCACHE_ALIGN, NULL);
void *obj = kmem_cache_alloc(my_cache, GFP_KERNEL);
// используем объект
kmem_cache_free(my_cache, obj); // возвращаем его в кэш
SLAB хорошо подходит для серверных систем с большим количеством параллельных запросов.
Как работает SLOB?
SLOB — это супер минималистичный аллокатор, который, в отличие от SLAB, ориентирован на минимальные накладные расходы и максимальную экономию памяти. Он напоминает работу стандартной кучи, как malloc в пользовательском пространстве. Внутри SLOB работает с небольшими блоками памяти, что делает его очень простым и эффективным для устройств с ограниченными ресурсами.Как это работает?
- Свободные блоки (Free List). В SLOB нет кэшей, как в SLAB, и объекты выделяются динамически из блоков памяти. Аллокатор хранит список свободных блоков, из которых выделяются объекты. Когда объект освобождается, он возвращается в свободный список, что делает алгоритм простым, но приводит к фрагментации.
- Аллокация памяти. SLOB работает как простая куча, выделяя ровно столько памяти, сколько нужно. Если фрагментация слишком высока и не удаётся найти подходящий блок, выделяется новый.
- Экономия памяти. Поскольку SLOB выделяет ровно столько памяти, сколько необходимо, без использования больших slab'ов, он оптимален для систем, где важно экономить каждый байт.
void *data = slob_alloc(128);
if (data) {
// Работаем с выделенной памятью
slob_free(data); // Освобождаем память
}
SLOB выделяет блок, минимально необходимый для объекта
В чем разница между SLAB и SLOB?
Характеристика | SLAB | SLOB |
---|---|---|
Подходит для | Высоконагруженные системы | Встраиваемые системы |
Управление памятью | Использует кэши для объектов одинакового размера | Прямое управление блоками памяти |
Фрагментация | Минимальная за счёт использования slab'ов | Высокая из-за простого управления блоками |
Производительность | Высокая за счёт кэширования объектов и минимальной фрагментации | Низкая при большом количестве мелких объектов |
Накладные расходы | Высокие, из-за сложного механизма кэширования и поддержки SMP | Минимальные, за счёт простоты реализации |
SLUB
SLUB использует упрощённую структуру по сравнению со SLAB. Он не поддерживает такие понятия, как кэш объектов, и не хранит метаданные о каждом объекте в отдельной структуре. Вместо этого SLUB хранит свободные блоки памяти прямо внутри slab'ов.Каждый процессор имеет свой собственный активный slab, что оптимизирует работу многопроцессорных систем и минимизирует задержки при выделении памяти.
Пример структуры в SLUB:
struct kmem_cache_cpu {
void **freelist; // Список свободных блоков памяти
struct page *page; // Текущая страница slab'а
};
В этом примере freelist — это указатель на свободные блоки памяти, которые могут быть быстро выделены для новых объектов. Вместо создания сложных кэшей, как в SLAB, SLUB просто хранит указатели на свободные объекты прямо в slab'ах.
Что выбрать
Динамическое управление памятью в Linux реализовано через несколько аллокаторов, каждый из которых решает свои задачи. SLAB дает высокую производительность за счёт кэширования объектов и минимизации фрагментации, что идеально подходит для серверных систем с высокой нагрузкой. SLOB фокусируется на экономии памяти и минимальных накладных расходах, что делает его лучшим выбором для встраиваемых устройств с ограниченными ресурсами. SLUB является упрощённой и улучшенной версией SLAB, дает более быструю работу, особенно в многопроцессорных системах.Коротко о SLAB, SLOB и SLYB в Linux
Привет! Когда речь заходит о динамическом управлении памятью в Linux, мы имеем дело с несколькими разными подходами, каждый из которых имеет свои плюсы и минусы. В этой статье...
habr.com