首页 > 系统相关 >内存分配指南 【ChatGPT】

内存分配指南 【ChatGPT】

时间:2023-12-09 16:11:24浏览次数:34  
标签:指南 KERNEL GFP 内存 分配器 使用 ChatGPT 分配

内存分配指南

Linux提供了各种用于内存分配的API。您可以使用kmalloc或kmem_cache_alloc系列来分配小块内存,使用vmalloc及其衍生物来分配大的虚拟连续区域,或者直接使用alloc_pages从页面分配器请求页面。还可以使用更专门的分配器,例如cma_alloc或zs_malloc。

大多数内存分配API使用GFP标志来表达应该如何分配该内存。GFP缩写代表"get free pages",即底层内存分配函数。

分配API的多样性结合众多的GFP标志使得问题“我应该如何分配内存?”并不容易回答,尽管很可能您应该使用

kzalloc(<size>, GFP_KERNEL);

当然,在某些情况下,必须使用其他分配API和不同的GFP标志。

获取空闲页标志

GFP标志控制分配器的行为。它们指示可以使用哪些内存区域,分配器应该尝试多努力找到空闲内存,内存是否可以被用户空间访问等。《Documentation/core-api/mm-api.rst》提供了GFP标志及其组合的参考文档,在这里我们简要概述它们的推荐用法:

  • 大多数情况下,GFP_KERNEL是您需要的。内核数据结构的内存,可进行DMA的内存,索引节点缓存,所有这些以及许多其他分配类型都可以使用GFP_KERNEL。请注意,使用GFP_KERNEL意味着使用GFP_RECLAIM,这意味着在内存压力下可能会触发直接回收;调用上下文必须允许休眠。

  • 如果分配是从原子上下文执行的,例如中断处理程序,请使用GFP_NOWAIT。此标志会阻止直接回收和IO或文件系统操作。因此,在内存压力下,GFP_NOWAIT分配可能会失败。具有合理回退的分配应该使用GFP_NOWARN。

  • 如果您认为访问内存保留是合理的,并且内核将受到压力,除非分配成功,您可以使用GFP_ATOMIC。

  • 从用户空间触发的不受信任的分配应该受到kmem记账的约束,并且必须设置__GFP_ACCOUNT位。有一个方便的GFP_KERNEL_ACCOUNT快捷方式,用于应该记账的GFP_KERNEL分配。

  • 用户空间分配应该使用GFP_USER、GFP_HIGHUSER或GFP_HIGHUSER_MOVABLE标志。标志名称越长,限制性越小。

  • GFP_HIGHUSER_MOVABLE不要求分配的内存将直接可被内核访问,并且意味着数据是可移动的。

  • GFP_HIGHUSER表示分配的内存不可移动,但不要求内核直接访问。一个例子可能是将数据直接映射到用户空间的硬件分配,但没有寻址限制。

  • GFP_USER表示分配的内存不可移动,并且必须直接可被内核访问。

您可能会注意到现有代码中有相当多的分配指定了GFP_NOIO或GFP_NOFS。从历史上看,它们用于防止由直接内存回收调用FS或IO路径并在已持有资源上阻塞而导致递归死锁。自4.12以来,解决此问题的首选方法是使用《Documentation/core-api/gfp_mask-from-fs-io.rst》中描述的新的范围API。

其他传统的GFP标志是GFP_DMA和GFP_DMA32。它们用于确保分配的内存可被具有有限寻址能力的硬件访问。因此,除非您正在为具有此类限制的设备编写驱动程序,否则应避免使用这些标志。即使对于具有限制的硬件,最好也使用dma_alloc* API。

GFP标志和回收行为

内存分配可能会触发直接或后台回收,了解页面分配器将尝试满足某个请求的程度是很有用的。

  • GFP_KERNEL & ~__GFP_RECLAIM - 乐观分配,根本不尝试释放任何内存。最轻量级的模式,甚至不会触发后台回收。应该谨慎使用,因为它可能会耗尽内存,下一个用户可能会遇到更激进的回收。

  • GFP_KERNEL & ~__GFP_DIRECT_RECLAIM(或GFP_NOWAIT)- 乐观分配,当前上下文不尝试从当前上下文释放内存,但如果区域低于低水位标记,可以唤醒kswapd回收内存。可以从原子上下文使用,或者当请求是性能优化时,并且有另一个慢路径的回退。

  • (GFP_KERNEL|__GFP_HIGH)& ~__GFP_DIRECT_RECLAIM(又名GFP_ATOMIC)- 非休眠分配,具有昂贵的回退,因此可以访问一些内存保留部分。通常从中断/底半部上下文使用,具有昂贵的慢路径回退。

  • GFP_KERNEL - 允许后台和直接回收,并使用默认的页面分配器行为。这意味着不昂贵的分配请求基本上不会失败,但不能保证这种行为,因此调用者必须适当检查失败(例如,OOM killer受害者当前允许失败)。

  • GFP_KERNEL | __GFP_NORETRY - 覆盖默认的分配器行为,所有分配请求会提前失败,而不会引起破坏性的回收(在此实现中进行一轮回收)。不会调用OOM killer。

  • GFP_KERNEL | __GFP_RETRY_MAYFAIL - 覆盖默认的分配器行为,所有分配请求会非常努力。如果回收无法取得任何进展,请求将失败。不会触发OOM killer。

  • GFP_KERNEL | __GFP_NOFAIL - 覆盖默认的分配器行为,所有分配请求将无休止地循环,直到成功。这可能非常危险,特别是对于较大的订单。

选择内存分配器

分配内存的最直接方式是使用kmalloc()系列的函数。为了安全起见,最好使用将内存设置为零的例程,如kzalloc()。如果需要为数组分配内存,可以使用kmalloc_array()和kcalloc()辅助函数。struct_size()、array_size()和array3_size()这些辅助函数可以用于安全地计算对象大小而不会溢出。

使用kmalloc分配的块的最大大小是有限的。实际限制取决于硬件和内核配置,但是最好的做法是对小于页面大小的对象使用kmalloc。

使用kmalloc()分配的块的地址至少对齐到ARCH_KMALLOC_MINALIGN字节。对于大小为2的幂的大小,也保证至少对齐到相应的大小。

使用kmalloc()分配的块可以使用krealloc()重新调整大小。类似于kmalloc_array():提供了一个用于调整数组大小的辅助函数krealloc_array()。

对于大型分配,可以使用vmalloc()和vzalloc(),或直接从页面分配器请求页面。vmalloc及其相关函数分配的内存在物理上不是连续的。

如果您不确定分配大小是否太大而无法使用kmalloc,可以使用kvmalloc()及其衍生物。它将尝试使用kmalloc分配内存,如果分配失败,则将使用vmalloc重试。对于kvmalloc可以使用的GFP标志有一些限制;请参阅kvmalloc_node()的参考文档。请注意,kvmalloc可能返回不是物理连续的内存。

如果需要分配许多相同的对象,可以使用slab缓存分配器。在使用之前,应该使用kmem_cache_create()或kmem_cache_create_usercopy()设置缓存。如果缓存的一部分可能被复制到用户空间,则应该使用第二个函数。创建缓存后,kmem_cache_alloc()及其便利包装器可以从该缓存中分配内存。

当不再需要分配的内存时,必须释放它。

使用kmalloc分配的对象可以使用kfree或kvfree释放。使用kmem_cache_alloc分配的对象可以使用kmem_cache_free、kfree或kvfree释放,后两者可能更方便,因为不需要kmem_cache指针。

相同的规则适用于释放函数的_bulk和_rcu变体。

使用vmalloc分配的内存可以使用vfree或kvfree释放。使用kvmalloc分配的内存可以使用kvfree释放。使用kmem_cache_create创建的缓存应该在释放所有分配的对象之后使用kmem_cache_destroy释放。

标签:指南,KERNEL,GFP,内存,分配器,使用,ChatGPT,分配
From: https://www.cnblogs.com/pengdonglin137/p/17891098.html

相关文章

  • Volatility2.6内存取证工具安装及入门Linux和Windows下安装
    (Volatility2.6内存取证工具安装及入门Linux和Windows下安装)1-1.Volatility2.6简介Volatility是一个完全开源的工具,用于从内存(RAM)样本中提取数字工件。支持Windows,Linux,MaC,Android等多类型操作系统系统的内存取证。那么针对竞赛这块(CTF、技能大赛等)基本上都是用在Misc方......
  • Java开发者的Python快速进修指南:实战之跳表pro版本
    之前我们讲解了简易版的跳表,我希望你能亲自动手实现一个更完善的跳表,同时也可以尝试实现其他数据结构,例如动态数组或哈希表等。通过实践,我们能够发现自己在哪些方面还有所欠缺。这些方法只有在熟练掌握之后才会真正理解,就像我在编写代码的过程中,难免会忘记一些方法或如何声明属性等......
  • 核心API文档 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/core-api/index.html#memory-management核心API文档这是核心内核API手册的开头部分。非常感谢您进行文档的转换和编写!核心实用程序本节包含一般和“核心核心”文档。首先是一大堆来自docbook时代的kerneldoc信息,实际上应该在有人有精......
  • 写入内核文档注释 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/doc-guide/kernel-doc.html写入内核文档注释Linux内核源文件中可能包含内核文档格式的结构化文档注释,用于描述代码的函数、类型和设计。将文档嵌入到源文件中可以更容易地保持文档的最新状态。注意内核文档格式与javadoc、gtk-doc或D......
  • Unreliable Guide To Locking 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/kernel-hacking/locking.htmlRusty'sRemarkablyUnreliableGuidetoKernelLocking作者RustyRussell简介欢迎阅读Rusty'sRemarkablyUnreliableGuidetoKernelLockingissues。本文档描述了LinuxKernel2.6中的锁定系统......
  • 内存可见于内存可用
    在GPU执行过程中有责任保证接下来访问的这块内存是保证有效的,也就是确保先前写入的数据对目标单元可见。简单介绍一下GPUCache体系,平时听得比较多的是CPUCache,但是GPU同样有着自己的Cache体系。如下图所示,在这里可以看GPU同样是有着L1/L2Cache的架构。 那么在GPU中是如何......
  • 内存分配
    这里主要讲一下模拟过程中遇到的问题和想法首先,为了保证模拟正确,我们应该以时间为参考对象去模拟,这样比以即将进入的任务或者等待队列中的任务为参考对象讨论的情况更少,犯的错误更少,每到达一个新时间如果有任务进入或者有任务完成就可以进行处理其次,这道题目的\(N\)非常大,所以我......
  • 一些指南(Yuxin Craft)
    一些指南文章的一些约定:[]所包含的内容是可以是任意字符串,相关提示在中括号内假人相关创建假人/player[username]spawn例如输入指令/playerniggerspawn将会创建一个名为nigger的假人到你的位置注意:服务器由于一些未知原因,创建部分假人的时候会出现卡顿。尤其......
  • Linux 内核黑客不可靠指南【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/kernel-hacking/hacking.htmlRustyRussell's"UnreliableGuidetoHackingtheLinuxKernel"作者RustyRussell简介欢迎阅读Rusty'sRemarkablyUnreliableGuidetoLinuxKernelHacking。本文档描述了内核代码的常见例程和一......
  • 发现工作负载使用的 Linux 内核子系统 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/admin-guide/workload-tracing.html发现工作负载使用的Linux内核子系统作者[email protected]@gmail.com维护者[email protected]要点了解构建和运行工......