Можно сказать, что свойства флага GFP_ATOMIC
лежат на противоположном конце спектра. Так как этот флаг указывает, что операция выделения памяти не может переходить в состояние ожидания, то такая операция очень ограничена в том, какую память можно использовать для выделения. Если нет доступного участка памяти заданного размера, то ядро, скорее всего, не будет пытаться освободить память, поскольку вызывающий код не может переходить в состояние ожидания. При использовании флага GFP_KERNEL
, наоборот, ядро может перевести вызывающий код в состояние ожидания, чтобы во время ожидания вытеснить страницы на диск (swap out), очистить измененные страницы памяти путем записи их в дисковый файл (flush dirty pages) и т.д. Поскольку при использовании флага GFP_ATOMIC
нет возможности выполнить ни одну из этих операций, то и шансов успешно выполнить выделение памяти тоже меньше (по крайней мере, когда в системе недостаточно памяти). Тем не менее использование флага GFP_ATOMIC
— это единственная возможность, когда вызывающий код не может переходить в состояние ожидания, как в случае обработчиков прерываний и нижних половин.
По своим свойствам между рассмотренными флагами находятся флаги GFP_NOIC
и GFP_NOFS
. Операции выделения памяти, которые запущены с этими флагами, могут блокироваться, но они воздерживаются от выполнения некоторых действий. Выделение памяти с флагом GFP_NOIO
не будет запускать никаких операций дискового ввода-вывода. С другой стороны, при использовании флага GFP_NOFS
могут запускаться операции дискового ввода-вывода, но не могут запускаться операции файловых систем. Когда эти флаги могут быть полезны? Они соответственно необходимы для определенного низкоуровневого кода блочного ввода-вывода или кода файловых систем. Представьте себе, что в некотором часто используемом участке кода файловых систем используется выделение памяти GFP_NOFS
. Если выделение памяти требует выполнения операций файловой системы, то выделение памяти приведет к еще
Флаг GFP_DMA
применяется для указания, что система выделения памяти должна при выполнении запроса предоставить память из зоны ZONE_DMA
. Этот флаг используется драйверами устройств, для которых необходимо выполнение операций прямого доступа к памяти. Обычно этот флаг должен комбинироваться с флагами GFP_ATOMIC
или GFP_KERNEL
.
В подавляющем большинстве случаев при разработке кода вам будет необходимо использовать флаги GFP_ATOMIC
или GFP_KERNEL
. В табл. 11.7 показано какие флаги и в каких ситуациях необходимо использовать. Независимо от типа операции выделения памяти, необходимо проверять результат и обрабатывать ошибки.
Таблица 11.7. Какой флаг и когда необходимо использовать
Ситуация | Решение |
---|---|
Контекст процесса, можно переходить в состояние ожидания | Используется флаг GFP_KERNEL |
Контекст процесса, нельзя переходить в состояние ожидания | Используется флаг GFP_ATOMIC или память выделяется с использованием флага GFP_KERNEL но в более ранний или поздний момент, когда можно переходить в состояние ожидания |
Обработчик прерывания | Используется флаг GFP_ATOMIC |
Обработка нижней половины | Используется флаг GFP_ATOMIC |
Необходима память для выполнения операций ПДП, можно переходить в состояние ожидания | Используются флаги (GFP_DMA | GFP_KERNEL) |
Необходима память для выполнения операций ПДП, нельзя переходить в состояние ожидания | Используются флаги (GFP_DMA | GFP_ATOMIC) или выделение выполняется в более поздний или более ранний момент времени |
Функция kfree()
Обратной к функции kmalloc()
является функция kfree()
, которая определена в файле
следующим образом.
void kfree(const void *ptr);