В чем разница между «__GFP_NOFAIL» и «__GFP_REPEAT»? - PullRequest
1 голос
/ 20 июня 2020

Согласно документации (https://www.linuxjournal.com/article/6930), в которой написано:

Flag           Description
__GFP_REPEAT   The kernel repeats the allocation if it fails.
__GFP_NOFAIL   The kernel can repeat the allocation.

Итак, оба они могут заставить ядро ​​повторить операцию выделения. Как я могу выбирать между ними? В чем основные отличия?

1 Ответ

1 голос
/ 20 июня 2020

Это на самом деле не «документация», а просто статья в LinuxJournal. Конечно, автор (Роберт Лав), несомненно, разбирается в предмете, но, тем не менее, эти описания довольно неточны и устарели (статья датирована 2003 годом).

Флаг __GFP_REPEAT был переименован в __GFP_RETRY_MAYFAIL в версия ядра 4.13 (см. соответствующий патч ) и его семантика также были изменены.

Исходное значение __GFP_REPEAT было (из include/linux/gfp.h kernel v4.12 ):

__GFP_REPEAT: Try hard to allocate the memory, but the allocation attempt
  _might_ fail.  This depends upon the particular VM implementation.

Имя и семанти c этого флага были несколько неясны, а новый флаг __GFP_RETRY_MAYFAIL имеет гораздо более четкое имя и описание (из include/linux/gfp.h ядра v5 .7.2 ):

%__GFP_RETRY_MAYFAIL: The VM implementation will retry memory reclaim
procedures that have previously failed if there is some indication
that progress has been made else where.  It can wait for other
tasks to attempt high level approaches to freeing memory such as
compaction (which removes fragmentation) and page-out.
There is still a definite limit to the number of retries, but it is
a larger limit than with %__GFP_NORETRY.
Allocations with this flag may fail, but only when there is
genuinely little unused memory. While these allocations do not
directly trigger the OOM killer, their failure indicates that
the system is likely to need to use the OOM killer soon.  The
caller must handle failure, but can reasonably do so by failing
a higher-level request, or completing it only in a much less
efficient manner.
If the allocation does fail, and the caller is in a position to
free some non-essential memory, doing so could benefit the system
as a whole.

Согласно __GFP_NOFAIL вы можете найти подробное описание в том же файле :

%__GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
cannot handle allocation failures. The allocation could block
indefinitely but will never return with failure. Testing for
failure is pointless.
New users should be evaluated carefully (and the flag should be
used only when there is no reasonable failure policy) but it is
definitely preferable to use the flag rather than opencode endless
loop around allocator.
Using this flag for costly allocations is _highly_ discouraged.

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

Излишне говорить, что флаг __GFP_NOFAIL должен использоваться с осторожностью только в сценарии ios, в котором другой вариант невозможен. Это полезно тем, что позволяет избежать явного вызова распределителя в al oop до тех пор, пока запрос не завершится успешно (например, while (!kmalloc(...));), и, следовательно, он более эффективен.

...