Чтение онлайн

на главную

Жанры

Разработка ядра Linux
Шрифт:

* обращаться по адресу, который хранится в переменной 'page'

*/

Значение

GFP_KERNEL
, которое передается в качестве параметра, — это пример флага
gfp_mask
, который скоро будет рассмотрен детально.

Обратите внимание на проверку ошибок после вызова функции

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

Низкоуровневые функции выделения памяти полезны, когда

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

Функция

kmalloc

Функция

kmalloc
работает аналогично функции
malloc
пространства пользователя, за исключением того, что добавляется еще один параметр
flags
. Функция
kmalloc
— это простой интерфейс для выделения в ядре участков памяти размером в заданное количество байтов. Если необходимы смежные страницы физической памяти, особенно когда их количество близко целой степени двойки, то ранее рассмотренные интерфейсы могут оказаться лучшим выбором. Однако для большинства операций выделения памяти в ядре функция
kmalloc
— наиболее предпочтительный интерфейс.

Рассматриваемая функция определена в файле

<linux/slab.h>
следующим образом.

void * kmalloc(size_t size, int flags);

Данная функция возвращает указатель на участок памяти, который имеет размер хотя бы

size
байт [63] . Выделенный участок памяти содержит физически смежные страницы. В случае ошибки функция возвращает значение
NULL
. Выделение памяти в ядре заканчивается успешно, только если доступно достаточное количество памяти. Поэтому после вызова функции
kmalloc
всегда необходимо проверять возвращаемое значение на равенство значению
NULL
и соответственным образом обрабатывать ошибку.

63

Данная функция может выделить памяти больше, чем указано, и нет никакой возможности узнать, на сколько больше! Поскольку в своей основе система выделения памяти в ядре базируется на страницах, некоторые запросы на выделение памяти могут округляться, чтобы хорошо вписываться е области доступной памяти. Ядро никогда не выделит меньше памяти, чем необходимо. Если ядро не в состоянии найти хотя бы указанное количество байтов, то операция завершится неудачно и функции возвратит значение

NULL
.

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

dog
.

struct dog *ptr;

ptr = kmalloc(sizeof (struct dog), GFP_KERNEL);

if (!ptr)

 /* здесь обработать ошибку ... */

Если вызов функции

kmalloc
завершится успешно, то переменная
ptr
будет указывать на область памяти, размер которой больше указанного значения или равен ему. Флаг
GFP_KERNEL
определяет тип поведения системы выделения памяти, когда она пытается выделить необходимую память при вызове функции
kmalloc
.

Флаги

gfp_mask

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

kmalloc
. Теперь давайте рассмотрим их более детально.

Флаги разбиты на три категории: модификаторы операций, модификаторы зон и флаги типов. Модификаторы операций указывают, каким образом ядро должно выделять указанную память. В некоторых ситуациях только некоторые методы могут использоваться для выделения памяти. Например, обработчики прерываний могут потребовать от ядра, что нельзя переходить в состояние ожидания при выделении памяти (поскольку обработчики прерывания не могут быть перепланированы), Модификаторы зоны указывают, откуда нужно выделять память. Как было рассказано, ядро делит физическую память на несколько зон, каждая из которых служит для различных целей. Модификаторы зоны указывают, из какой зоны выделять память. Флаги типов представляют собой различные комбинации модификаторов операций и зон, которые необходимы для определенного типа

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

Модификаторы операций

Все флаги, включая модификаторы операций, определены в заголовочном файле

<linux/gfp.h>
. Подключение файла
<linux/slab.h>
также подключает и этот заголовочный файл, поэтому его не часто приходится подключать явно. На практике обычно лучше использовать флаги типов, которые будут рассмотрены дальше. Тем не менее полезно иметь представление об индивидуальных флагах. В табл. 11.3 показан список модификаторов операций.

Таблица 11.3. Модификаторы операций

Флаг Описание
__GFP_WAIT
Операция выделения памяти может переводить текущий процесс в состояние ожидания
__GFP_HIGH
Операция выделения памяти может обращаться к аварийным запасам
__GFP_IO
Операция выделения памяти может использовать дисковые операции ввода-вывода
__GFP_FS
Операция выделения памяти может использовать операции ввода- вывода файловой системы
__GFP_COLD
Операция выделения памяти должна использовать страницы памяти, содержимое которых не находится в кэше процессора (cache cold)
__GFP_NOWARN
Операция выделения памяти не будет печатать сообщения об ошибках
__GFP_REPEAT
Операция выделения памяти повторит попытку выделения в случае ошибки
__GFP_NOFAIL
Операция выделения памяти будет повторять попытки выделения неопределенное количество раз
__GFP_NORETRY
Операция выделения памяти никогда не будет повторять попытку выделения памяти
__GFP_NO_GROW
Используется внутри слябового распределителя памяти (slab layer)
__GFP_COMP
Добавить метаданные составной (compound) страницы памяти. Используется кодом поддержки больших страниц памяти (hugetlb)

Описанные модификаторы можно указывать вместе, как показано в следующем примере.

ptr = kmalloc(size, __GFP_WAIT | __GFP_IO | __GFP_FS);

Этот код дает инструкцию ядру (а именно функции

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

Большинство запросов на выделение памяти указывают эти модификаторы, но это делается косвенным образом с помощью флагов типа, которые скоро будут рассмотрены. Не нужно волноваться, у вас не будет необходимости каждый раз разбираться, какие из этих ужасных флагов использовать при выделении памяти!

Модификаторы зоны

Модификаторы зоны указывают, из какой зоны должна выделяться память. Обычно выделение может происходить из любой зоны. Однако ядро предпочитает зону

ZONE_NORMAL
, чтобы гарантировать, что в других зонах, когда это необходимо, есть свободные страницы.

Существует всего два модификатора зоны, поскольку, кроме зоны

ZONE_NORMAL
(из которой по умолчанию идет выделение памяти), существует всего две зоны. В табл. 11.4 приведен список модификаторов зоны.

Таблица 11.4. Модификаторы зоны

Флаг Описание
__GFP_DMA
Выделять память только из зоны
ZONE_DMA
__GFP_HIGHMEM
Выделять память только из зон
ZONE_HIGHMEM
и
ZONE_NORMAL
Поделиться:
Популярные книги

На границе империй. Том 7. Часть 5

INDIGO
11. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 7. Часть 5

Скрываясь в тени

Мазуров Дмитрий
2. Теневой путь
Фантастика:
боевая фантастика
7.84
рейтинг книги
Скрываясь в тени

Пятничная я. Умереть, чтобы жить

Это Хорошо
Фантастика:
детективная фантастика
6.25
рейтинг книги
Пятничная я. Умереть, чтобы жить

Точка Бифуркации V

Смит Дейлор
5. ТБ
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Точка Бифуркации V

Я же бать, или Как найти мать

Юнина Наталья
Любовные романы:
современные любовные романы
6.44
рейтинг книги
Я же бать, или Как найти мать

Невеста клана

Шах Ольга
Фантастика:
попаданцы
фэнтези
5.00
рейтинг книги
Невеста клана

На распутье

Кронос Александр
2. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
На распутье

Поцелуй тьмы

Мид Райчел
3. Академия вампиров
Фантастика:
ужасы и мистика
9.53
рейтинг книги
Поцелуй тьмы

Сопряжение 9

Астахов Евгений Евгеньевич
9. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
технофэнтези
рпг
5.00
рейтинг книги
Сопряжение 9

Великий князь

Кулаков Алексей Иванович
2. Рюрикова кровь
Фантастика:
альтернативная история
8.47
рейтинг книги
Великий князь

Последний попаданец 5

Зубов Константин
5. Последний попаданец
Фантастика:
юмористическая фантастика
рпг
5.00
рейтинг книги
Последний попаданец 5

Попала, или Кто кого

Юнина Наталья
Любовные романы:
современные любовные романы
5.88
рейтинг книги
Попала, или Кто кого

Безымянный раб [Другая редакция]

Зыков Виталий Валерьевич
1. Дорога домой
Фантастика:
боевая фантастика
9.41
рейтинг книги
Безымянный раб [Другая редакция]

Огненный князь 5

Машуков Тимур
5. Багряный восход
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Огненный князь 5