Linux Device Drivers 3 / Драйверы устройств Линукс (третье издание): 8.1. The Real Story of kmalloc

Оглавление
Английский оригинал Перевод на русский

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

8.1 Вся правда о kmalloc.

VectorVT44Mil 21.03.11 в 19:16

0

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

VectorVT44Mil 21.03.11 в 19:31

0

[1] Среди прочего, это подразумевает, что Вы должны явным образом очистить память, которая может быть использована в юзерспейсе или для записи в устройство; в противном случае, Вы рискуете раскрыть информацию, которая должна оставаться приватной.

VectorVT44Mil 21.03.11 в 19:34

0

8.1.1. Аргумент флаги
Запомните как выглядит прототип:
#include
void *kmalloc(size_t size, int flags);

VectorVT44Mil 21.03.11 в 19:34

0

Первый аргумент kmalloc это размер выделяемого блока. Второй аргумент, флаги выделения, значительно интереснее, так как контролирует различные стороны поведения kmalloc.

VectorVT44Mil 21.03.11 в 19:40

0

Наиболее часто используемый флаг, GFP_KERNEL, означает, что выделение памяти (внутренне выполняемое через вызов __get_free_pages, являющейся исходником GFP_prefix ) выполняется от имени процесса выполняющегося с приоритетом уровня ядра. Другими словами, это значит что запуск функции приводит к системному вызову от имени процесса. Используя GFP_KERNEL означает, что kmalloc может заставить процесс уснуть в ожидании свободной страницы памяти если вызов произошел в момент ее недостатка. Функция, выделяющая память, используя GFP_KERNEL, должна, тем не менее, быть повторно входимой и не может быть запущена во время атомарной операции. Пока текущий процесс спит, ядро выполняет необходимые операции для выделения свободной памяти, сбрасывая буферы на диск или свопируя память самого процесса.

VectorVT44Mil 21.03.11 в 19:57

0

Не всегда полезно использовать флаг GFP_KERNEL; иногда kmalloc вызывается за пределами контекста процесса. Такой тип вызова может случиться, например, в обработчиках прерываний, тасклетах и таймерах ядра. В этом случае, текущий процесс не уснет, и драйвер должен использовать флаг GFP_ATOMIC вместо этого. На самом деле, ядро старается иметь в запасе несколько страниц памяти чтобы поддерживать атомарные операции выделения памяти. Когда Вы используете GFP_ATOMIC, kmalloc может использовать даже самые последние странички. Однако, если этих последних страниц нет, то выделение закончится неудачей.

VectorVT44Mil 22.03.11 в 18:42

0

Другие флаги можно использовать вместе с GFP_KERNEL и GFP_ATOMIC, или вместо них, хотя эти два удовлетворяют большую часть потребностей драйверов устройств. Все флаги определены в , индивидуальные флаги имеют префикс с двойным подчеркиванием, вроде __GFP_DMA. В добавок, наиболее употребимые комбинации флагов не имеют префикса и их иногда называют"предпочтения выделения". Вот они:

VectorVT44Mil 22.03.11 в 18:54

0

GFP_ATOMIC
Используется для выделения памяти за пределами контекста процесса. Процесс не засыпает.

VectorVT44Mil 22.03.11 в 18:55

0

GFP_KERNEL
Нормальное выделение памяти ядра. Процесс может уснуть.

VectorVT44Mil 22.03.11 в 18:57

0

GFP_USER
Используется для выделения памяти для страниц в юзерспейсе. Процесс может уснуть.

VectorVT44Mil 22.03.11 в 18:58

0

GFP_HIGHUSER
Работает так же как и GFP_USER, но выделение происходит в верхней памяти, если она есть. Верхняя память описана в следующем подразделе.

VectorVT44Mil 22.03.11 в 18:59

0

GFP_NOIO
GFP_NOFS
Эти флаги работают как GFP_KERNEL, но для них есть ограничения в действиях ядра направленных на обработку данного запроса. GFP_NOFS запрещает использовать какие-либо вызовы файловой системы, а GFP_NOIO запрещает любой ввод/вывод вообще. Они используются главным образом в коде файловой системы и виртуальной памяти где процесс выделения может быть прерван, тогда как рекурсивные вызовы файловой системы являются очень плохой идеей.

VectorVT44Mil 22.03.11 в 19:05

0

Флаги, описанные выше, могут дополняться с помощью побитового ИЛИ следующими флагами, которые изменяют алгоритм выделения:

VectorVT44Mil 22.03.11 в 19:07

0

__GFP_DMA
Этот флаг запрашивает память из зоны, котоая может быть использована для DMA. Конкретное значение зависит от платформы и обсуждается в следующем разделе.

VectorVT44Mil 22.03.11 в 19:10

0

__GFP_HIGHMEM
Этот флаг говорит, что выделяемая память может размещаться в верхней памяти.

VectorVT44Mil 22.03.11 в 19:12

0

__GFP_COLD
Обычно, аллокатор памяти пытается вернуть "кэш-теплые" страницы, т.е. страницы, которые недавно оказывались в кэше процессора. Этот флаг напротив, запрашивает холодные страницы, т.е. те которые не использовались уже некоторое время. Это полезно для выделения страниц для чтения через DMA, где бесполезна связь страницы памяти с кэшем. Полное описание выделения буферов для DMA находится в Главе 15 .

VectorVT44Mil 22.03.11 в 19:18

0

__GFP_NOWARN
Этот флаг используется редко, он заставляет ядро не выводить предупреждения (с помощью printk) когда выделение памяти невозможно.

VectorVT44Mil 22.03.11 в 19:20

0

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

VectorVT44Mil 22.03.11 в 19:25

0

__GFP_REPEAT
__GFP_NOFAIL
__GFP_NORETRY
Эти флаги определяют поведение аллокатора когда есть трудности с выделением. __GFP_REPEAT подразумевает "постарайся немного лучше" повторив попытку, но выделение все еще может закончиться неудачей. __GFP_NOFAIL говорит аллокатору, что нужно выполнить запрос во что бы то ни стало; и он пашет как проклятый, пытаясь выполнить задание. Использование __GFP_NOFAIL очень и очень нежелательно; по правде сказать, вряд ли найдутся убедительные причины использовать это флаг в драйвере устройства. И наконец, __GFP_NORETRY говорит аллокатору оставить попытки немедленно если запрашиваемая память недоступна.

VectorVT44Mil 22.03.11 в 19:33

0
Минутку...