Wsphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextEnglish}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget/core-api/memory-allocationmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget./translations/zh_TW/core-api/memory-allocationmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget./translations/it_IT/core-api/memory-allocationmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget./translations/ja_JP/core-api/memory-allocationmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget./translations/ko_KR/core-api/memory-allocationmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget./translations/sp_SP/core-api/memory-allocationmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageChinese (Simplified)uh1h hh _documenthsourceNlineNubhnote)}(hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。h]h paragraph)}(hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。h]hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hh5Documentation/translations/zh_CN/disclaimer-zh_CN.rsthKhhubah}(h]h ]h"]h$]h&]uh1hhhhhhhhNubh field_list)}(hhh](hfield)}(hhh](h field_name)}(hOriginalh]hOriginal}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhh[/var/lib/git/docbuild/linux/Documentation/translations/zh_CN/core-api/memory-allocation.rsthKubh field_body)}(h-Documentation/core-api/memory-allocation.rst h]h)}(h,Documentation/core-api/memory-allocation.rsth]h,Documentation/core-api/memory-allocation.rst}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(h翻译h]h翻译}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhKubh)}(h-司延腾 Yanteng Si h]h)}(h,司延腾 Yanteng Si h](h司延腾 Yanteng Si <}(hjhhhNhNubh reference)}(hsiyanteng@loongson.cnh]hsiyanteng@loongson.cn}(hjhhhNhNubah}(h]h ]h"]h$]h&]refurimailto:siyanteng@loongson.cnuh1jhjubh>}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(h校译h]h校译}(hjAhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj>hhhKubh)}(h时奎亮 h]h)}(h时奎亮 h](h 时奎亮 <}(hjShhhNhNubj)}(halexs@kernel.orgh]halexs@kernel.org}(hj[hhhNhNubah}(h]h ]h"]h$]h&]refurimailto:alexs@kernel.orguh1jhjSubh>}(hjShhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK hjOubah}(h]h ]h"]h$]h&]uh1hhj>ubeh}(h]h ]h"]h$]h&]uh1hhhhK hhhhubeh}(h]h ]h"]h$]h&]uh1hhhhhhhhKubhtarget)}(h".. _cn_core-api_memory-allocation:h]h}(h]h ]h"]h$]h&]refidcn-core-api-memory-allocationuh1jhKhhhhhhubhsection)}(hhh](htitle)}(h内存分配指南h]h内存分配指南}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjhhhhhKubh)}(hXQLinux为内存分配提供了多种API。你可以使用 `kmalloc` 或 `kmem_cache_alloc` 系列分配小块内存,使用 `vmalloc` 及其派生产品分配大的几乎连续的区域,或者 你可以用 alloc_pages 直接向页面分配器请求页面。也可以使用更专业的分配器, 例如 `cma_alloc` 或 `zs_malloc` 。h](h9Linux为内存分配提供了多种API。你可以使用 }(hjhhhNhNubhtitle_reference)}(h `kmalloc`h]hkmalloc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 或 }(hjhhhNhNubj)}(h`kmem_cache_alloc`h]hkmem_cache_alloc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh# 系列分配小块内存,使用 }(hjhhhNhNubj)}(h `vmalloc`h]hvmalloc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 及其派生产品分配大的几乎连续的区域,或者 你可以用 alloc_pages 直接向页面分配器请求页面。也可以使用更专业的分配器, 例如 }(hjhhhNhNubj)}(h `cma_alloc`h]h cma_alloc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 或 }hjsbj)}(h `zs_malloc`h]h zs_malloc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(h大多数的内存分配API使用GFP标志来表达该内存应该如何分配。GFP的缩写代表 “(get free pages)获取空闲页”,是底层的内存分配功能。h]h大多数的内存分配API使用GFP标志来表达该内存应该如何分配。GFP的缩写代表 “(get free pages)获取空闲页”,是底层的内存分配功能。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(h(内存)分配API的多样性与众多的GFP标志相结合,使得“我应该如何分配内存?”这个问 题不那么容易回答,尽管很可能你应该使用h]h(内存)分配API的多样性与众多的GFP标志相结合,使得“我应该如何分配内存?”这个问 题不那么容易回答,尽管很可能你应该使用}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh literal_block)}(hkzalloc(, GFP_KERNEL);h]hkzalloc(, GFP_KERNEL);}hj2sbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1j0hhhK hjhhubh)}(hK当然,有些情况下必须使用其他分配API和不同的GFP标志。h]hK当然,有些情况下必须使用其他分配API和不同的GFP标志。}(hjBhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK"hjhhubj)}(hhh](j)}(h获取空闲页标志h]h获取空闲页标志}(hjShhhNhNubah}(h]h ]h"]h$]h&]uh1jhjPhhhhhK%ubh)}(hX;GFP标志控制分配器的行为。它们告诉我们哪些内存区域可以被使用,分配器应该多努力寻 找空闲的内存,这些内存是否可以被用户空间访问等等。内存管理API为GFP标志和它们的 组合提供了参考文件,这里我们简要介绍一下它们的推荐用法:h]hX;GFP标志控制分配器的行为。它们告诉我们哪些内存区域可以被使用,分配器应该多努力寻 找空闲的内存,这些内存是否可以被用户空间访问等等。内存管理API为GFP标志和它们的 组合提供了参考文件,这里我们简要介绍一下它们的推荐用法:}(hjahhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK&hjPhhubh block_quote)}(hXn* 大多数时候, ``GFP_KERNEL`` 是你需要的。内核数据结构的内存,DMA可用内存,inode 缓存,所有这些和其他许多分配类型都可以使用 ``GFP_KERNEL`` 。注意,使用 ``GFP_KERNEL`` 意味着 ``GFP_RECLAIM`` ,这意味着在有内存压力的情况下可能会触发直接回收;调用上 下文必须允许睡眠。 * 如果分配是从一个原子上下文中进行的,例如中断处理程序,使用 ``GFP_NOWAIT`` 。这个 标志可以防止直接回收和IO或文件系统操作。因此,在内存压力下, ``GFP_NOWAIT`` 分配 可能会失败。有合理退路的分配应该使用 ``GFP_NOWARN`` 。 * 如果你认为访问保留内存区是合理的,并且除非分配成功,否则内核会有压力,你可以使用 ``GFP_ATOMIC`` 。 * 从用户空间触发的不可信任的分配应该是kmem核算的对象,必须设置 ``__GFP_ACCOUNT`` 位。 有一个方便的用于 ``GFP_KERNEL`` 分配的 ``GFP_KERNEL_ACCOUNT`` 快捷键,其应该被核 算。 * 用户空间的分配应该使用 ``GFP_USER`` 、 ``GFP_HIGHUSER`` 或 ``GFP_HIGHUSER_MOVABLE`` 中的一个标志。标志名称越长,限制性越小。 ``GFP_HIGHUSER_MOVABLE`` 不要求分配的内存将被内核直接访问,并意味着数据是可迁移的。 ``GFP_HIGHUSER`` 意味着所分配的内存是不可迁移的,但也不要求它能被内核直接访问。举个 例子就是一个硬件分配内存,这些数据直接映射到用户空间,但没有寻址限制。 ``GFP_USER`` 意味着分配的内存是不可迁移的,它必须被内核直接访问。 h]h bullet_list)}(hhh](h list_item)}(hXf大多数时候, ``GFP_KERNEL`` 是你需要的。内核数据结构的内存,DMA可用内存,inode 缓存,所有这些和其他许多分配类型都可以使用 ``GFP_KERNEL`` 。注意,使用 ``GFP_KERNEL`` 意味着 ``GFP_RECLAIM`` ,这意味着在有内存压力的情况下可能会触发直接回收;调用上 下文必须允许睡眠。 h]h)}(hXe大多数时候, ``GFP_KERNEL`` 是你需要的。内核数据结构的内存,DMA可用内存,inode 缓存,所有这些和其他许多分配类型都可以使用 ``GFP_KERNEL`` 。注意,使用 ``GFP_KERNEL`` 意味着 ``GFP_RECLAIM`` ,这意味着在有内存压力的情况下可能会触发直接回收;调用上 下文必须允许睡眠。h](h大多数时候, }(hjhhhNhNubhliteral)}(h``GFP_KERNEL``h]h GFP_KERNEL}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 是你需要的。内核数据结构的内存,DMA可用内存,inode 缓存,所有这些和其他许多分配类型都可以使用 }(hjhhhNhNubj)}(h``GFP_KERNEL``h]h GFP_KERNEL}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 。注意,使用 }(hjhhhNhNubj)}(h``GFP_KERNEL``h]h GFP_KERNEL}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 意味着 }(hjhhhNhNubj)}(h``GFP_RECLAIM``h]h GFP_RECLAIM}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhq ,这意味着在有内存压力的情况下可能会触发直接回收;调用上 下文必须允许睡眠。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK*hj|ubah}(h]h ]h"]h$]h&]uh1jzhjwubj{)}(hX+如果分配是从一个原子上下文中进行的,例如中断处理程序,使用 ``GFP_NOWAIT`` 。这个 标志可以防止直接回收和IO或文件系统操作。因此,在内存压力下, ``GFP_NOWAIT`` 分配 可能会失败。有合理退路的分配应该使用 ``GFP_NOWARN`` 。 h]h)}(hX*如果分配是从一个原子上下文中进行的,例如中断处理程序,使用 ``GFP_NOWAIT`` 。这个 标志可以防止直接回收和IO或文件系统操作。因此,在内存压力下, ``GFP_NOWAIT`` 分配 可能会失败。有合理退路的分配应该使用 ``GFP_NOWARN`` 。h](hX如果分配是从一个原子上下文中进行的,例如中断处理程序,使用 }(hjhhhNhNubj)}(h``GFP_NOWAIT``h]h GFP_NOWAIT}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhe 。这个 标志可以防止直接回收和IO或文件系统操作。因此,在内存压力下, }(hjhhhNhNubj)}(h``GFP_NOWAIT``h]h GFP_NOWAIT}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh? 分配 可能会失败。有合理退路的分配应该使用 }(hjhhhNhNubj)}(h``GFP_NOWARN``h]h GFP_NOWARN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK/hjubah}(h]h ]h"]h$]h&]uh1jzhjwubj{)}(h如果你认为访问保留内存区是合理的,并且除非分配成功,否则内核会有压力,你可以使用 ``GFP_ATOMIC`` 。 h]h)}(h如果你认为访问保留内存区是合理的,并且除非分配成功,否则内核会有压力,你可以使用 ``GFP_ATOMIC`` 。h](hy如果你认为访问保留内存区是合理的,并且除非分配成功,否则内核会有压力,你可以使用 }(hj0hhhNhNubj)}(h``GFP_ATOMIC``h]h GFP_ATOMIC}(hj8hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj0ubh 。}(hj0hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK3hj,ubah}(h]h ]h"]h$]h&]uh1jzhjwubj{)}(h从用户空间触发的不可信任的分配应该是kmem核算的对象,必须设置 ``__GFP_ACCOUNT`` 位。 有一个方便的用于 ``GFP_KERNEL`` 分配的 ``GFP_KERNEL_ACCOUNT`` 快捷键,其应该被核 算。 h]h)}(h从用户空间触发的不可信任的分配应该是kmem核算的对象,必须设置 ``__GFP_ACCOUNT`` 位。 有一个方便的用于 ``GFP_KERNEL`` 分配的 ``GFP_KERNEL_ACCOUNT`` 快捷键,其应该被核 算。h](hY从用户空间触发的不可信任的分配应该是kmem核算的对象,必须设置 }(hjZhhhNhNubj)}(h``__GFP_ACCOUNT``h]h __GFP_ACCOUNT}(hjbhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjZubh! 位。 有一个方便的用于 }(hjZhhhNhNubj)}(h``GFP_KERNEL``h]h GFP_KERNEL}(hjthhhNhNubah}(h]h ]h"]h$]h&]uh1jhjZubh 分配的 }(hjZhhhNhNubj)}(h``GFP_KERNEL_ACCOUNT``h]hGFP_KERNEL_ACCOUNT}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjZubh# 快捷键,其应该被核 算。}(hjZhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK5hjVubah}(h]h ]h"]h$]h&]uh1jzhjwubj{)}(hXM用户空间的分配应该使用 ``GFP_USER`` 、 ``GFP_HIGHUSER`` 或 ``GFP_HIGHUSER_MOVABLE`` 中的一个标志。标志名称越长,限制性越小。 ``GFP_HIGHUSER_MOVABLE`` 不要求分配的内存将被内核直接访问,并意味着数据是可迁移的。 ``GFP_HIGHUSER`` 意味着所分配的内存是不可迁移的,但也不要求它能被内核直接访问。举个 例子就是一个硬件分配内存,这些数据直接映射到用户空间,但没有寻址限制。 ``GFP_USER`` 意味着分配的内存是不可迁移的,它必须被内核直接访问。 h](h)}(h用户空间的分配应该使用 ``GFP_USER`` 、 ``GFP_HIGHUSER`` 或 ``GFP_HIGHUSER_MOVABLE`` 中的一个标志。标志名称越长,限制性越小。h](h"用户空间的分配应该使用 }(hjhhhNhNubj)}(h ``GFP_USER``h]hGFP_USER}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 、 }(hjhhhNhNubj)}(h``GFP_HIGHUSER``h]h GFP_HIGHUSER}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 或 }(hjhhhNhNubj)}(h``GFP_HIGHUSER_MOVABLE``h]hGFP_HIGHUSER_MOVABLE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh= 中的一个标志。标志名称越长,限制性越小。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK9hjubh)}(hp``GFP_HIGHUSER_MOVABLE`` 不要求分配的内存将被内核直接访问,并意味着数据是可迁移的。h](j)}(h``GFP_HIGHUSER_MOVABLE``h]hGFP_HIGHUSER_MOVABLE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhX 不要求分配的内存将被内核直接访问,并意味着数据是可迁移的。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjubh)}(h[``GFP_USER`` 意味着分配的内存是不可迁移的,它必须被内核直接访问。h](j)}(h ``GFP_USER``h]hGFP_USER}(hj(hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj$ubhO 意味着分配的内存是不可迁移的,它必须被内核直接访问。}(hj$hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKAhjubeh}(h]h ]h"]h$]h&]uh1jzhjwubeh}(h]h ]h"]h$]h&]bullet*uh1juhhhK*hjqubah}(h]h ]h"]h$]h&]uh1johhhK*hjPhhubh)}(hX你可能会注意到,在现有的代码中,有相当多的分配指定了 ``GFP_NOIO`` 或 ``GFP_NOFS`` 。 从历史上看,它们被用来防止递归死锁,这种死锁是由直接内存回收调用到FS或IO路径以及对已 经持有的资源进行阻塞引起的。从4.12开始,解决这个问题的首选方法是使用新的范围API,即 :ref:`Documentation/core-api/gfp_mask-from-fs-io.rst `.h](hO你可能会注意到,在现有的代码中,有相当多的分配指定了 }(hjThhhNhNubj)}(h ``GFP_NOIO``h]hGFP_NOIO}(hj\hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjTubh 或 }(hjThhhNhNubj)}(h ``GFP_NOFS``h]hGFP_NOFS}(hjnhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjTubh 。 从历史上看,它们被用来防止递归死锁,这种死锁是由直接内存回收调用到FS或IO路径以及对已 经持有的资源进行阻塞引起的。从4.12开始,解决这个问题的首选方法是使用新的范围API,即 }(hjThhhNhNubh)}(hK:ref:`Documentation/core-api/gfp_mask-from-fs-io.rst `h]hinline)}(hjh]h.Documentation/core-api/gfp_mask-from-fs-io.rst}(hjhhhNhNubah}(h]h ](xrefstdstd-refeh"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]refdoc-translations/zh_CN/core-api/memory-allocation refdomainjreftyperef refexplicitrefwarn reftargetgfp_mask_from_fs_iouh1hhhhKChjTubh.}(hjThhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKChjPhhubh)}(hXG其他传统的GFP标志是 ``GFP_DMA`` 和 ``GFP_DMA32`` 。它们用于确保分配的内存可以被寻 址能力有限的硬件访问。因此,除非你正在为一个有这种限制的设备编写驱动程序,否则要避免 使用这些标志。而且,即使是有限制的硬件,也最好使用dma_alloc* APIs。h](h其他传统的GFP标志是 }(hjhhhNhNubj)}(h ``GFP_DMA``h]hGFP_DMA}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 和 }(hjhhhNhNubj)}(h ``GFP_DMA32``h]h GFP_DMA32}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhX 。它们用于确保分配的内存可以被寻 址能力有限的硬件访问。因此,除非你正在为一个有这种限制的设备编写驱动程序,否则要避免 使用这些标志。而且,即使是有限制的硬件,也最好使用dma_alloc* APIs。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKHhjPhhubj)}(hhh](j)}(hGFP标志和回收行为h]hGFP标志和回收行为}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjhhhhhKMubh)}(h内存分配可能会触发直接或后台回收,了解页面分配器将如何努力满足该请求或其他请求是非常 有用的。h]h内存分配可能会触发直接或后台回收,了解页面分配器将如何努力满足该请求或其他请求是非常 有用的。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKNhjhhubjp)}(hX* ``GFP_KERNEL & ~__GFP_RECLAIM`` - 乐观分配,完全不尝试释放内存。最轻量级的模 式,甚至不启动后台回收。应该小心使用,因为它可能会耗尽内存,而下一个用户可能会启 动更积极的回收。 * ``GFP_KERNEL & ~__GFP_DIRECT_RECLAIM`` (or ``GFP_NOWAIT`` ) - 乐观分配,不 试图从当前上下文中释放内存,但如果该区域低于低水位,可以唤醒kswapd来回收内存。可 以从原子上下文中使用,或者当请求是一个性能优化,并且有另一个慢速路径的回退。 * ``(GFP_KERNEL|__GFP_HIGH) & ~__GFP_DIRECT_RECLAIM`` (aka ``GFP_ATOMIC`` ) - 非 睡眠分配,有一个昂贵的回退,所以它可以访问某些部分的内存储备。通常从中断/底层上下 文中使用,有一个昂贵的慢速路径回退。 * ``GFP_KERNEL`` - 允许后台和直接回收,并使用默认的页面分配器行为。这意味着廉价 的分配请求基本上是不会失败的,但不能保证这种行为,所以失败必须由调用者适当检查(例 如,目前允许OOM杀手失败)。 * ``GFP_KERNEL | __GFP_NORETRY`` - 覆盖默认的分配器行为,所有的分配请求都会提前 失败,而不是导致破坏性的回收(在这个实现中是一轮的回收)。OOM杀手不被调用。 * ``GFP_KERNEL | __GFP_RETRY_MAYFAIL`` - 覆盖 **默认** 的分配器行为,所有分配请求都非 常努力。如果回收不能取得任何进展,该请求将失败。OOM杀手不会被触发。 * ``GFP_KERNEL | __GFP_NOFAIL`` - 覆盖默认的分配器行为,所有分配请求将无休止地循 环,直到成功。这可能真的很危险,特别是对于较大的需求。 h]jv)}(hhh](j{)}(h``GFP_KERNEL & ~__GFP_RECLAIM`` - 乐观分配,完全不尝试释放内存。最轻量级的模 式,甚至不启动后台回收。应该小心使用,因为它可能会耗尽内存,而下一个用户可能会启 动更积极的回收。 h]h)}(h``GFP_KERNEL & ~__GFP_RECLAIM`` - 乐观分配,完全不尝试释放内存。最轻量级的模 式,甚至不启动后台回收。应该小心使用,因为它可能会耗尽内存,而下一个用户可能会启 动更积极的回收。h](j)}(h``GFP_KERNEL & ~__GFP_RECLAIM``h]hGFP_KERNEL & ~__GFP_RECLAIM}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh - 乐观分配,完全不尝试释放内存。最轻量级的模 式,甚至不启动后台回收。应该小心使用,因为它可能会耗尽内存,而下一个用户可能会启 动更积极的回收。}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKQhjubah}(h]h ]h"]h$]h&]uh1jzhjubj{)}(hX:``GFP_KERNEL & ~__GFP_DIRECT_RECLAIM`` (or ``GFP_NOWAIT`` ) - 乐观分配,不 试图从当前上下文中释放内存,但如果该区域低于低水位,可以唤醒kswapd来回收内存。可 以从原子上下文中使用,或者当请求是一个性能优化,并且有另一个慢速路径的回退。 h]h)}(hX9``GFP_KERNEL & ~__GFP_DIRECT_RECLAIM`` (or ``GFP_NOWAIT`` ) - 乐观分配,不 试图从当前上下文中释放内存,但如果该区域低于低水位,可以唤醒kswapd来回收内存。可 以从原子上下文中使用,或者当请求是一个性能优化,并且有另一个慢速路径的回退。h](j)}(h&``GFP_KERNEL & ~__GFP_DIRECT_RECLAIM``h]h"GFP_KERNEL & ~__GFP_DIRECT_RECLAIM}(hj5hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj1ubh (or }(hj1hhhNhNubj)}(h``GFP_NOWAIT``h]h GFP_NOWAIT}(hjGhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj1ubhX ) - 乐观分配,不 试图从当前上下文中释放内存,但如果该区域低于低水位,可以唤醒kswapd来回收内存。可 以从原子上下文中使用,或者当请求是一个性能优化,并且有另一个慢速路径的回退。}(hj1hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKUhj-ubah}(h]h ]h"]h$]h&]uh1jzhjubj{)}(hX``(GFP_KERNEL|__GFP_HIGH) & ~__GFP_DIRECT_RECLAIM`` (aka ``GFP_ATOMIC`` ) - 非 睡眠分配,有一个昂贵的回退,所以它可以访问某些部分的内存储备。通常从中断/底层上下 文中使用,有一个昂贵的慢速路径回退。 h]h)}(hX``(GFP_KERNEL|__GFP_HIGH) & ~__GFP_DIRECT_RECLAIM`` (aka ``GFP_ATOMIC`` ) - 非 睡眠分配,有一个昂贵的回退,所以它可以访问某些部分的内存储备。通常从中断/底层上下 文中使用,有一个昂贵的慢速路径回退。h](j)}(h3``(GFP_KERNEL|__GFP_HIGH) & ~__GFP_DIRECT_RECLAIM``h]h/(GFP_KERNEL|__GFP_HIGH) & ~__GFP_DIRECT_RECLAIM}(hjmhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjiubh (aka }(hjihhhNhNubj)}(h``GFP_ATOMIC``h]h GFP_ATOMIC}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjiubh ) - 非 睡眠分配,有一个昂贵的回退,所以它可以访问某些部分的内存储备。通常从中断/底层上下 文中使用,有一个昂贵的慢速路径回退。}(hjihhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKYhjeubah}(h]h ]h"]h$]h&]uh1jzhjubj{)}(hX``GFP_KERNEL`` - 允许后台和直接回收,并使用默认的页面分配器行为。这意味着廉价 的分配请求基本上是不会失败的,但不能保证这种行为,所以失败必须由调用者适当检查(例 如,目前允许OOM杀手失败)。 h]h)}(hX``GFP_KERNEL`` - 允许后台和直接回收,并使用默认的页面分配器行为。这意味着廉价 的分配请求基本上是不会失败的,但不能保证这种行为,所以失败必须由调用者适当检查(例 如,目前允许OOM杀手失败)。h](j)}(h``GFP_KERNEL``h]h GFP_KERNEL}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhX - 允许后台和直接回收,并使用默认的页面分配器行为。这意味着廉价 的分配请求基本上是不会失败的,但不能保证这种行为,所以失败必须由调用者适当检查(例 如,目前允许OOM杀手失败)。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK]hjubah}(h]h ]h"]h$]h&]uh1jzhjubj{)}(h``GFP_KERNEL | __GFP_NORETRY`` - 覆盖默认的分配器行为,所有的分配请求都会提前 失败,而不是导致破坏性的回收(在这个实现中是一轮的回收)。OOM杀手不被调用。 h]h)}(h``GFP_KERNEL | __GFP_NORETRY`` - 覆盖默认的分配器行为,所有的分配请求都会提前 失败,而不是导致破坏性的回收(在这个实现中是一轮的回收)。OOM杀手不被调用。h](j)}(h``GFP_KERNEL | __GFP_NORETRY``h]hGFP_KERNEL | __GFP_NORETRY}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh - 覆盖默认的分配器行为,所有的分配请求都会提前 失败,而不是导致破坏性的回收(在这个实现中是一轮的回收)。OOM杀手不被调用。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKahjubah}(h]h ]h"]h$]h&]uh1jzhjubj{)}(h``GFP_KERNEL | __GFP_RETRY_MAYFAIL`` - 覆盖 **默认** 的分配器行为,所有分配请求都非 常努力。如果回收不能取得任何进展,该请求将失败。OOM杀手不会被触发。 h]h)}(h``GFP_KERNEL | __GFP_RETRY_MAYFAIL`` - 覆盖 **默认** 的分配器行为,所有分配请求都非 常努力。如果回收不能取得任何进展,该请求将失败。OOM杀手不会被触发。h](j)}(h$``GFP_KERNEL | __GFP_RETRY_MAYFAIL``h]h GFP_KERNEL | __GFP_RETRY_MAYFAIL}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh - 覆盖 }(hjhhhNhNubhstrong)}(h **默认**h]h默认}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 的分配器行为,所有分配请求都非 常努力。如果回收不能取得任何进展,该请求将失败。OOM杀手不会被触发。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKdhjubah}(h]h ]h"]h$]h&]uh1jzhjubj{)}(h``GFP_KERNEL | __GFP_NOFAIL`` - 覆盖默认的分配器行为,所有分配请求将无休止地循 环,直到成功。这可能真的很危险,特别是对于较大的需求。 h]h)}(h``GFP_KERNEL | __GFP_NOFAIL`` - 覆盖默认的分配器行为,所有分配请求将无休止地循 环,直到成功。这可能真的很危险,特别是对于较大的需求。h](j)}(h``GFP_KERNEL | __GFP_NOFAIL``h]hGFP_KERNEL | __GFP_NOFAIL}(hj+hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj'ubh - 覆盖默认的分配器行为,所有分配请求将无休止地循 环,直到成功。这可能真的很危险,特别是对于较大的需求。}(hj'hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKghj#ubah}(h]h ]h"]h$]h&]uh1jzhjubeh}(h]h ]h"]h$]h&]jLjMuh1juhhhKQhjubah}(h]h ]h"]h$]h&]uh1johhhKQhjhhubeh}(h]gfpah ]h"]gfp标志和回收行为ah$]h&]uh1jhjPhhhhhKMubeh}(h]id2ah ]h"]获取空闲页标志ah$]h&]uh1jhjhhhhhK%ubj)}(hhh](j)}(h选择内存分配器h]h选择内存分配器}(hjhhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjehhhhhKkubh)}(hXp分配内存的最直接的方法是使用kmalloc()系列的函数。而且,为了安全起见,最好使用将内存 设置为零的例程,如kzalloc()。如果你需要为一个数组分配内存,有kmalloc_array()和kcalloc() 辅助程序。辅助程序struct_size()、array_size()和array3_size()可以用来安全地计算对 象的大小而不会溢出。h]hXp分配内存的最直接的方法是使用kmalloc()系列的函数。而且,为了安全起见,最好使用将内存 设置为零的例程,如kzalloc()。如果你需要为一个数组分配内存,有kmalloc_array()和kcalloc() 辅助程序。辅助程序struct_size()、array_size()和array3_size()可以用来安全地计算对 象的大小而不会溢出。}(hjvhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKmhjehhubh)}(h可以用 `kmalloc` 分配的块的最大尺寸是有限的。实际的限制取决于硬件和内核配置,但是对于 小于页面大小的对象,使用 `kmalloc` 是一个好的做法。h](h 可以用 }(hjhhhNhNubj)}(h `kmalloc`h]hkmalloc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 分配的块的最大尺寸是有限的。实际的限制取决于硬件和内核配置,但是对于 小于页面大小的对象,使用 }(hjhhhNhNubj)}(h `kmalloc`h]hkmalloc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 是一个好的做法。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKrhjehhubh)}(h用 `kmalloc` 分配的块的地址至少要对齐到ARCH_KMALLOC_MINALIGN字节。对于2的幂的大小, 对齐方式也被保证为至少是各自的大小。h](h用 }(hjhhhNhNubj)}(h `kmalloc`h]hkmalloc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 分配的块的地址至少要对齐到ARCH_KMALLOC_MINALIGN字节。对于2的幂的大小, 对齐方式也被保证为至少是各自的大小。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKuhjehhubh)}(h用kmalloc()分配的块可以用krealloc()调整大小。与kmalloc_array()类似:以krealloc_array() 的形式提供了一个用于调整数组大小的辅助工具。h]h用kmalloc()分配的块可以用krealloc()调整大小。与kmalloc_array()类似:以krealloc_array() 的形式提供了一个用于调整数组大小的辅助工具。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKxhjehhubh)}(h对于大量的分配,你可以使用vmalloc()和vzalloc(),或者直接向页面分配器请求页面。由vmalloc 和相关函数分配的内存在物理上是不连续的。h]h对于大量的分配,你可以使用vmalloc()和vzalloc(),或者直接向页面分配器请求页面。由vmalloc 和相关函数分配的内存在物理上是不连续的。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK{hjehhubh)}(hXy如果你不确定分配的大小对 `kmalloc` 来说是否太大,可以使用kvmalloc()及其派生函数。它将尝 试用kmalloc分配内存,如果分配失败,将用 `vmalloc` 重新尝试。对于哪些GFP标志可以与 `kvmalloc` 一起使用是有限制的;请看kvmalloc_node()参考文档。注意, `kvmalloc` 可能会返回物理上不连 续的内存。h](h%如果你不确定分配的大小对 }(hjhhhNhNubj)}(h `kmalloc`h]hkmalloc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh 来说是否太大,可以使用kvmalloc()及其派生函数。它将尝 试用kmalloc分配内存,如果分配失败,将用 }(hjhhhNhNubj)}(h `vmalloc`h]hvmalloc}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh/ 重新尝试。对于哪些GFP标志可以与 }(hjhhhNhNubj)}(h `kvmalloc`h]hkvmalloc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhM 一起使用是有限制的;请看kvmalloc_node()参考文档。注意, }(hjhhhNhNubj)}(h `kvmalloc`h]hkvmalloc}(hj0hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh/ 可能会返回物理上不连 续的内存。}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK~hjehhubh)}(hXn如果你需要分配许多相同的对象,你可以使用slab缓存分配器。在使用缓存之前,应该用 kmem_cache_create()或kmem_cache_create_usercopy()来设置缓存。如果缓存的一部分可能被复 制到用户空间,应该使用第二个函数。在缓存被创建后,kmem_cache_alloc()和它的封装可以从该缓 存中分配内存。h]hXn如果你需要分配许多相同的对象,你可以使用slab缓存分配器。在使用缓存之前,应该用 kmem_cache_create()或kmem_cache_create_usercopy()来设置缓存。如果缓存的一部分可能被复 制到用户空间,应该使用第二个函数。在缓存被创建后,kmem_cache_alloc()和它的封装可以从该缓 存中分配内存。}(hjHhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjehhubh)}(h当分配的内存不再需要时,它必须被释放。你可以使用kvfree()来处理用 `kmalloc` 、 `vmalloc` 和 `kvmalloc` 分配的内存。slab缓存应该用kmem_cache_free()来释放。不要忘记用 kmem_cache_destroy()来销毁缓存。h](h]当分配的内存不再需要时,它必须被释放。你可以使用kvfree()来处理用 }(hjVhhhNhNubj)}(h `kmalloc`h]hkmalloc}(hj^hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjVubh 、 }(hjVhhhNhNubj)}(h `vmalloc`h]hvmalloc}(hjphhhNhNubah}(h]h ]h"]h$]h&]uh1jhjVubh 和 }(hjVhhhNhNubj)}(h `kvmalloc`h]hkvmalloc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjVubhy 分配的内存。slab缓存应该用kmem_cache_free()来释放。不要忘记用 kmem_cache_destroy()来销毁缓存。}(hjVhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjehhubeh}(h]id3ah ]h"]选择内存分配器ah$]h&]uh1jhjhhhhhKkubeh}(h](jid1eh ]h"](内存分配指南cn_core-api_memory-allocationeh$]h&]uh1jhhhhhhhKexpect_referenced_by_name}jjsexpect_referenced_by_id}jjsubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(jN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh، _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}j]jasnameids}(jjjjjbj_jZjWjju nametypes}(jjjbjZjuh}(jjjjj_jPjWjjjeu footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}jKsRparse_messages]transform_messages]hsystem_message)}(hhh]h)}(hhh]hCHyperlink target "cn-core-api-memory-allocation" is not referenced.}hj<sbah}(h]h ]h"]h$]h&]uh1hhj9ubah}(h]h ]h"]h$]h&]levelKtypeINFOsourceh،lineKuh1j7uba transformerN include_log]?Documentation/translations/zh_CN/core-api/memory-allocation.rst(NNNNta decorationNhhub.