“__GFP_NOFAIL”和“__GFP_REPEAT”有什么区别?
What are the differences between "__GFP_NOFAIL" and "__GFP_REPEAT"?
根据文档 (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.
所以,两者都可能导致内核重复分配操作。
我该如何选择它们?
主要区别是什么?
那不是真正的“文档”,而只是 LinuxJournal 上的一篇文章。诚然,作者 (Robert Love) 肯定对这个主题很了解,但是这些描述非常不准确和过时(文章来自 2003 年)。
__GFP_REPEAT
标志在内核版本 4.13 中被重命名为 __GFP_RETRY_MAYFAIL
(参见 the relevant patchwork)并且其语义也被修改。
__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.
这个标志的名称和语义有点不清楚,新的 __GFP_RETRY_MAYFAIL
标志有更清晰的名称和描述(来自 include/linux/gfp.h
kernel 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
你可以找到详细的描述in the same file:
%__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
标志。它很有用,因为它避免在循环中显式调用分配器,直到请求成功(例如 while (!kmalloc(...));
),因此效率更高。
根据文档 (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.
所以,两者都可能导致内核重复分配操作。 我该如何选择它们? 主要区别是什么?
那不是真正的“文档”,而只是 LinuxJournal 上的一篇文章。诚然,作者 (Robert Love) 肯定对这个主题很了解,但是这些描述非常不准确和过时(文章来自 2003 年)。
__GFP_REPEAT
标志在内核版本 4.13 中被重命名为 __GFP_RETRY_MAYFAIL
(参见 the relevant patchwork)并且其语义也被修改。
__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.
这个标志的名称和语义有点不清楚,新的 __GFP_RETRY_MAYFAIL
标志有更清晰的名称和描述(来自 include/linux/gfp.h
kernel 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
你可以找到详细的描述in the same file:
%__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
标志。它很有用,因为它避免在循环中显式调用分配器,直到请求成功(例如 while (!kmalloc(...));
),因此效率更高。