Флаг |
Описание |
__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. Флаги типов
Флаг |
Описание |
GFP_ATOMIC |
Запрос на выделение памяти высокоприоритетный и в состояние ожидания переходить нельзя. Этот флаг предназначен для использования в обработчика: прерываний, нижних половин и в других ситуациях, когда нельзя переходить в состояние ожидания |
GFP_NOIO |
Запрос на выделение памяти может блокироваться, но при его выполнении нельзя выполнять операции дискового ввода-вывода. Этот флаг предназначен для использования в коде блочного ввода-вывода, когда нельзя инициировать новые операции ввода-вывода |
GFP_NOFS |
Запрос на выделение памяти может блокироваться и выполнять дисковые операции ввода-вывода, но запрещено выполнять операции, связанные с файловыми системами. Этот флаг предназначен для использования в коде файловых систем, когда нельзя начинать выполнение новых файловых операций |
GFP_KERNEL |
Обычный запрос на выделение памяти, который может блокироваться. Этот флаг предназначен для использования в коде, который выполняется в контексте процесса, когда безопасно переходить в состояние ожидания |
GFP_USER |
Обычный запрос на выделение памяти, который может блокироваться. Этот флаг используется для выделения памяти процессам пространства пользователя |
GFP_HIGHUSER |
Запрос на выделение памяти из зоны ZONE_HIGHMEM , который может блокироваться. Этот флаг используется для выделения памяти процессам пространства пользователя |
GFP_DMA |
Запрос на выделение памяти из зоны ZONE_DMA . Драйверам устройств, которым нужна память для выполнения операций по ПДП, необходимо использовать этот флаг обычно в комбинации с одним из описанных выше флагов |
Таблица 11.6. Список модификаторов, соответствующих каждому флагу типа
Флаг |
Модификаторы |
GFP_ATOMIC |
__GFP_HIGH |
GFP_NOIO |
__GFP_WAIT |
GFP_NOFS |
(__GFP_WAIT | __GFP_IO) |
GFP_KERNEL |
(__GFP_WAIT | __GFP_IO | __GFP_FS) |
GFP_USER |
(__GFP_WAIT | __GFP_IO | __GFP_FS) |
GFP_HIGHUSER |
(__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HIGHMEM) |
GFP_DMA |
__GFP_DMA |
Рассмотрим наиболее часто используемые флаги и для чего они могут быть нужны. Подавляющее большинство операций выделения памяти в ядре используют флаг GFP_KERNEL
. В результате операция выделения памяти имеет обычный приоритет и может переводить процесс в состояние ожидания. Поскольку этот вызов может блокироваться, его можно использовать только в контексте процесса, выполнение которого может быть безопасно перепланировано (т.е. нет удерживаемых блокировок и т.д.). При использовании этого флага нет никаких оговорок по поводу того, каким образом ядро может получить необходимую память, поэтому операция выделения памяти имеет большой шанс выполниться успешно.
Читать дальше