Пример использования слябового распределителя памяти

Пример использования слябового распределителя памяти

Давайте рассмотрим пример из реальной жизни, связанный с работой со структурами task_struct (дескрипторы процессов). Показанный ниже код в несколько более сложной форме приведен в файле kernel/fork.c.

В ядре определена глобальная переменная, в которой хранится указатель на кэш объектов task_struct:

kmem_cache_t *task_struct_cachep;

Во время инициализации ядра, в функции fork_init(), этот кэш создается следующим образом.

task_struct_cachep = kmem_cache_create("task_struct",

 sizeof(struct task_struct), ARCH_MIN_TASKALIGN,

 SLAB_PANIC, NULL, NULL);

Данный вызов создает кэш с именем "task_struct", который предназначен для хранения объектов тина struct task_struct. Объекты создаются с начальным смещением в слябе, равным ARCH_MIN_TASKALIGN байт, и положение всех объектов выравнивается по границам строк системного кэша, значение этого выравнивания зависит от аппаратной платформы. Обычно значение выравнивания задается для каждой аппаратной платформы с помощью определения препроцессора L1_CACHE_BYTES, которое равно размеру процессорного кэша первого уровня в байтах. Конструктор и деструктор отсутствуют. Следует обратить внимание, что возвращаемое значение не проверяется на равенство NULL, поскольку указан флаг SLAB_PANIC. В случае, когда при выделении памяти произошла ошибка, слябовый распределитель памяти вызовет функцию panic(). Если этот флаг не указан, то нужно проверять возвращаемое значение на равенство NULL, что сигнализирует об ошибке. Флаг SLAB_PANIC здесь используется потому, что этот каш является необходимым для работы системы (без дескрипторов процессов работать как-то не хорошо).

Каждый раз, когда процесс вызывает функцию fork(), должен создаваться новый дескриптор процесса (вспомните главу 3, "Управление процессами"). Это выполняется следующим образом в функции dup_task_struct(), которая вызывается из функции do_fork().

struct task_struct *tsk;

tsk = kmem_cache_alloc(task struct_cachep, GFP_KERNEL);

if (!tsk)

 return NULL;

Когда процесс завершается, если нет порожденных процессов, которые ожидают на завершение родительского процесса, то дескриптор освобождается и возвращается обратно в кэш task_struct_cachep. Эти действия выполняются в функции free_task_struct(), как показано ниже (где параметр tsk указывает на удаляемый дескриптор).

kmem_cache_free(task_struct_cachep, tsk);

Так как дескрипторы процессов принадлежат к основным компонентам ядра и всегда необходимы, то кэш task_struct_cachep никогда не ликвидируется. Если бы он ликвидировался, то делать это необходимо было бы следующим образом.

int err;

err = kmem_cache_destroy(task_struct_cachep);

if (err)

 /* ошибка ликвидации кэша */

Достаточно просто, не так ли? Уровень слябового распределения памяти скрывает все низкоуровневые операции, связанные с выравниванием, "раскрашиванием", выделением и освобождением памяти, "сборкой мусора" в случае нехватки памяти. Коли часто необходимо создавать много объектов одного типа, то следует подумать об использовании слябового кэша. И уж точно не нужно писать свою реализацию списка свободных ресурсов!

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

4.6. Пример построения диаграммы вариантов использования

Из книги Самоучитель UML автора Леоненков Александр

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


Пример использования

Из книги Разгони свой сайт автора Мациевский Николай

Пример использования В следующем примере сервер уведомляет Internet Explorer, что содержание документа не будет меняться в течение 1 часа (pre-check=3600) и что его можно загружать прямо из локального кэша. В случае же изменения страницы, если пользователь запросит ее по истечении 15


Пример использования рецептов

Из книги Сетевые средства Linux автора Смит Родерик В.

Пример использования рецептов Приведенные выше сведения были необходимы для создания общего представления о работе Procmail. В листинге приведен чрезвычайно простой пример файла Procmail, предназначенного для фильтрации сообщений. Содержащиеся в нем рецепты пригодны для


Глава 7 Средства отладки использования памяти

Из книги Разработка приложений в среде Linux. Второе издание автора Джонсон Майкл К.

Глава 7 Средства отладки использования памяти Несмотря на то что С бесспорно является стандартным языком программирования в системах Linux, он имеет ряд особенностей, не дающих программистам возможности писать код, не содержащий тонких ошибок, которые впоследствии очень


Пример использования Go To

Из книги VBA для чайников автора Каммингс Стив

Пример использования Go To В следующем примере оператор Go To направляет поток программы из главной части процедуры к метке Special Value, если встречается необычное значение: Function GoToExample (ItemNumber As Integer ) Dim intR As Integer Select Case ItemNumber Case 2412 Go To SpecialValue Case Is < CutOffValue DoSomething


Пример использования

Из книги Linux программирование в примерах автора Роббинс Арнольд

Пример использования Данный раздел не является частью GPL. Здесь мы показываем комментарий с заявлением об авторских правах из программы GNU env:/* env - run a program in a modified environmentCopyright (C) 1986, 1991-2002 Free Software Foundation, Inc.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as


7.2.6. Статистика использования процессом памяти

Из книги Программирование для Linux. Профессиональный подход автора Митчелл Марк

7.2.6. Статистика использования процессом памяти Файл statm содержит список из семи чисел, разделенных пробелами. Каждое число — это счетчик числа страниц памяти, используемых процессом и попадающих в определенную категорию. Соответствующие категории перечислены ниже (в


1.7.1. Пример использования команды chown

Из книги Linux и UNIX: программирование в shell. Руководство разработчика. автора Тейнсли Дэвид

1.7.1. Пример использования команды chown Вот как можно поменять владельца файла с помощью команды chown:$ ls -l-rwxrwxrwx 1 louise admin 345 Sep 20 14:33 project$ chown pauline project $ ls -l-rwxrwxrwx 1 pauline admin 345 Sep 20 14:33 projectПраво владения файлом project переходит от пользователя louise к


1.7.2. Пример использования команды chgrp

Из книги Разработка ядра Linux автора Лав Роберт

1.7.2. Пример использования команды chgrp Следующий пример демонстрирует, как поменять группу, которой принадлежит файл:$ ls -1-rwxrwxrwx 1 pauline admin 345 Sep 20 14:33 project$ chgrp sysadmin project $ ls -1-rwxrwxrwx 1 pauline sysadmin 345 Sep 20 14:33 projectПользователь pauline передал группе sysadmin право владения файлом project, которое до


Уровень слябового распределителя памяти

Из книги Описание языка PascalABC.NET автора Коллектив РуБоард

Уровень слябового распределителя памяти Выделение и освобождение структур данных — это одна из наиболее частых операций, которые выполняются в любом ядре. Для того чтобы облегчить процедуру частого выделения и освобождения данных при программировании, вводятся списки


Устройство слябового распределителя памяти

Из книги автора

Устройство слябового распределителя памяти Уровень слябового распределения памяти делит объекты на группы, которые называются кэшами (cache). Разные кэши используются для хранения объектов различных типов. Для каждого типа объектов существует свой уникальный кэш.


Интерфейс слябового распределителя памяти

Из книги автора

Интерфейс слябового распределителя памяти Новый кэш можно создать с помощью вызова следующей функции.kmem_cache_t * kmem_cache_create(const char *name, size_t size, size_t offset, unsigned long flags,void (*ctor)(void*, kmem_cache_t*, unsigned long),void (*dtor)(void*, kmem_cache_t*, unsigned long));Первый параметр — это строка, которая содержит имя кэша.


Пример использования таймера

Из книги автора

Пример использования таймера Данная программа выводит 1 каждые 100 миллисекунд в течение 3 секунд:uses Timers;procedure TimerProc;beginwrite(1);end;begin var t := new Timer(100,TimerProc);t.Start;Sleep(3000);end.Вызов Sleep здесь обязателен, иначе программа после создания таймера сразу закончится, и обработчик таймера ни