Этот код дает инструкцию ядру (а именно функции alloc_pages()
), что операция выделения памяти может быть блокирующей, выполнять операции ввода-вывода и операции файловой системы, если это необходимо. В данном случае ядру предоставляется большая свобода в отношении того, где оно будет искать необходимую память, чтобы удовлетворить запрос.
Большинство запросов на выделение памяти указывают эти модификаторы, но это делается косвенным образом с помощью флагов типа, которые скоро будут рассмотрены. Не нужно волноваться, у вас не будет необходимости каждый раз разбираться, какие из этих ужасных флагов использовать при выделении памяти!
Модификаторы зоны указывают, из какой зоны должна выделяться память. Обычно выделение может происходить из любой зоны. Однако ядро предпочитает зону ZONE_NORMAL
, чтобы гарантировать, что в других зонах, когда это необходимо, есть свободные страницы.
Существует всего два модификатора зоны, поскольку, кроме зоны ZONE_NORMAL
(из которой по умолчанию идет выделение памяти), существует всего две зоны. В табл. 11.4 приведен список модификаторов зоны.
Таблица 11.4. Модификаторы зоны
Флаг | Описание |
---|---|
__GFP_DMA | Выделять память только из зоны ZONE_DMA |
__GFP_HIGHMEM | Выделять память только из зон ZONE_HIGHMEM и ZONE_NORMAL |
Указание одного из этих флагов изменяет зону, из которой ядро пытается выделить память. Флаг __GFP_DMA
требует, чтобы ядро выделило память только из зоны ZONE_DMA
Этот флаг эквивалентен следующему высказыванию в форме жесткого требования: "__GFP_HIGHMEM
, наоборот, требует, чтобы выделение памяти было из зон ZONE_NORMAL
и ZONE_HIGHMEM
(вторая более предпочтительна). Этот флаг эквивалентен запросу: "
Если не указан ни один из флагов, то ядро пытается выделять память из зон ZONE_NORMAL
и ZONE_DMA
, отдавая значительное предпочтение зоне ZONE_NORMAL
.
Флаг __GFP_HIGHMEM
нельзя укалывать при вызове функций __get_free_pages()
или kmalloc()
. Это связано с тем, что они возвращают логический адрес, а не структуру page, и появляется возможность, что эти функции выделят память, которая в данный момент не отображается в виртуальное адресное пространство ядра и поэтому не имеет логического адреса. Только функция alloc_pages()
может выделять страницы в верхней памяти. Однако в большинстве случаев в запросах на выделение памяти не нужно указывать модификаторы зоны, так как достаточно того, что используется зона ZONE_NORMAL
.
Флаги типов указывают модификаторы операций и зон, которые необходимы для выполнения запросов определенных типов. В связи с этим, в коде ядра стараются использовать правильный флаг типа и не использовать больших наборов модификаторов. Это одновременно и проще и при этом меньше шансов ошибиться. В табл. 11.5 приведен список возможных флагов типов, а в табл. 11.6 показано, какие модификаторы соответствуют какому флагу.
Таблица 11.5. Флаги типов