0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux内核中用GFP_ATOMIC申请内存意味着什么

Linux阅码场 来源:Linuxer 作者:Linuxer 2021-01-04 13:43 次阅读

本文目的

本文补充校正一些Linux内核开发者关于GFP_ATOMIC的认知不完整的地方,阐述GFP_ATOMIC与free内存watermark的关系,并明确什么时候应该用GFP_ATOMIC申请内存。目录:

1. GFP_ATOMICvs. GFP_KERNEL

2. 内存水位,PF_MEMALLOC和GFP_ATOMIC

3. 何时使用GFP_ATOMIC(一个patch分析)

GFP_ATOMICvs. GFP_KERNEL

我们都知道,在中断、软中断、spinlock等原子上下文里面,申请内存,应该使用GFP_ATOMIC标记,譬如内核中有大量的kmalloc/GFP_ATOMIC的例子:

fd0acb90-4e4c-11eb-8b86-12bb97331649.png

对于不可睡眠的上下文,如果我们用常规的GFP_KERNEL这样的标记去申请内存,可能引发直接的内存reclaim,从而引起睡眠,所以GFP_KERNEL这种标记只适合进程上下文调用:

fd396c0c-4e4c-11eb-8b86-12bb97331649.png

GFP_KERNEL的标记可以引发直接的内存回收,从而导致进程阻塞睡眠,这在原子上下文显然是不允许的。

#define GFP_KERNEL (__GFP_RECLAIM | __GFP_IO | __GFP_FS) #define __GFP_RECLAIM ((__force gfp_t)(___GFP_DIRECT_RECLAIM|___GFP_KSWAPD_RECLAIM)

内存水位,PF_MEMALLOC和GFP_ATOMIC

那么GFP_ATOMIC是否仅仅意味着不能睡眠呢?档案是否定的,GFP_ATOMIC还与内存reclaim的水位相关。下面这个图是讲述水位watermark的一个著名的图,笔者懒得画了,直接从网下copy过来:

fda0690c-4e4c-11eb-8b86-12bb97331649.jpg

在Linux中,内存有3个水位:

HIGH:系统的free内存大于HIGH水位的时候,是一个相对保险的值,不需要急着做内存回收(reclaim);

LOW: 系统的free内存达到LOW水位的时候,启动后台kswapd进行内存回收,回收的目标是让空闲内存达到HIGH水位;

MIN:系统应该保有的最小free内存,当空闲内存达到这个值的时候,kswapd的后台回收可能来不及了,一般用户在申请内存的时候,进行DIRECT RECLAIM。

min水位一般是系统自动换算的,其具体值可以从/proc看出:

# cat /proc/sys/vm/min_free_kbytes 45056

而LOW水位一般是min*125%,HIGH 一般是min*150%。

MIN水位以下的内存,只能被紧急情况下的用户申请到,最著名的紧急用户莫过于PF_MEMALLOC用户,task_struct设置了这个标记表示忽略MIN水位。比如回收内存的代码本身也可能需要申请内存,这个时候我们应该给它无限制的申请能力。典型地,比如kswapd就设置了这个标记,这个代码里面的注释也非常精彩:

fddec24c-4e4c-11eb-8b86-12bb97331649.png

如果我们不允许回收内存的代码申请min以下的内存,则回收内存的代码可以触发回收内存,这样“子子孙孙,无穷匮也”。

当然,PF_MEMALLOC不是唯一的紧急用户,GFP_ATOMIC实际也是一个“半紧急”任务:

说它“紧急”,是因为如果原子上下文申请内存失败,往往意味着相应的中断、软中断、spinlock内部的代码就会执行失败,而我们又不会因为这种失败,而去尝试内存回收,这显然比较惨,我们应该尽可能让GFP_ATOMIC申请成功;

说它“半”,是因为它不至于紧急到PF_MEMALLOC这个程度,如果我们给它无限地申请到free内存为0的权力,则会导致PF_MEMALLOC没有内存了。想想,如果征粮队的人都饿死了,还怎么去征粮呢?

所以,内存的设计选择是,当有人用GFP_ATOMIC申请内存的时候,允许它从MIN水位以下,申请一定数量的内存。什么叫“一定数量”呢?就是不能让GFP_ATOMIC导致free 内存触底,GFP_ATOMIC还包含了高优先级的含义:

#define GFP_ATOMIC (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)

注意这个里面的__GFP_HIGH不是HIGHMEM高端内存的意思,而是高优先级。

当我们用GFP_ATOMIC申请内存的时候,内核的水位检查代码,会允许我们触及到MIN水位以下的1/2:

fe13730c-4e4c-11eb-8b86-12bb97331649.png

那么,“魔鬼”就是在画红圈的2行代码。但是,如果我们进一步深究,会发现,GFP_ATOMIC不只是触及1/2*min,它甚至可以触及1/4*min,因为GFP_ATOMIC中的__GFP_HIGH让ALLOC_HIGH成立,而__GFP_ATOMIC让ALLOC_HARDER成立:

fe5222dc-4e4c-11eb-8b86-12bb97331649.png

所以,“魔鬼”又隐藏在了gfp_to_alloc_flags()的细节里。

一个patch的例子

在具体的工程实战中,我们建议:

原子上下文使用GFP_ATOMIC

比如在网络设备驱动drivers/net/ethernet中,就有大量的案例

fe6582dc-4e4c-11eb-8b86-12bb97331649.png

在内存紧急的路径上(比如不想睡眠,要求低延迟;或者要求内存吃紧的情况下,仍然可以从min水位以下申请内存),哪怕是进程上下文,我们也建议可以考虑使用GFP_ATOMIC

比如田涛童鞋最近在mm/zswap.c发的RFC patch:

https://lore.kernel.org/linux-mm/1608894171-54174-2-git-send-email-tiantao6@hisilicon.com/

fe85c902-4e4c-11eb-8b86-12bb97331649.png

fea50934-4e4c-11eb-8b86-12bb97331649.png

上面2个地方,其实都是可以睡眠的进程上下文,但是我们认为在frontendswap的路径上,我们对延迟敏感,对swap内存过程中进一步引发内存回收也担忧,因此,这里哪怕是非原子上下文,我们也没有使用GFP_KERNEL。

责任编辑:xj

原文标题:宋宝华:Linux内核中用GFP_ATOMIC申请内存究竟意味着什么?

文章出处:【微信公众号:Linuxer】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内核
    +关注

    关注

    3

    文章

    1309

    浏览量

    39846
  • Linux
    +关注

    关注

    87

    文章

    10990

    浏览量

    206734
  • GFP
    GFP
    +关注

    关注

    0

    文章

    5

    浏览量

    1362

原文标题:宋宝华:Linux内核中用GFP_ATOMIC申请内存究竟意味着什么?

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    可以在RTOS的任何位置使用malloc申请内存了吗?

    今天看了CubeIDE 1.7.0的release note ,里面写的一条新特性是:Thread-safe malloc solution 这是否意味着我可以在RTOS的任何位置使用malloc申请内存了?
    发表于 04-03 07:23

    Linux内核内存管理之内核非连续物理内存分配

    的主要优点是避免了外部碎片,而缺点是需要修改内核页表。显然,非连续内存区域的大小必须是4096的倍数。Linux使用非连续物理内存区的场景有几种:(1)为swap区分配数据结构;(2)
    的头像 发表于 02-23 09:44 378次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b><b class='flag-5'>内存</b>管理之<b class='flag-5'>内核</b>非连续物理<b class='flag-5'>内存</b>分配

    ADM1191本身芯片电源为3.15到26V,是否意味着SENSE端只能测试接近这个范围的电压?

    小弟我是一个尚在学习过程的学生,现如今试图用ADM1191芯片测试其他电路的电流, 有两个问题想要请教: 1、ADM1191本身芯片电源为3.15到26V,是否意味着SENSE端只能测试接近这个
    发表于 01-09 06:15

    Linux内核内存管理架构解析

    内存管理子系统可能是linux内核中最为复杂的一个子系统,其支持的功能需求众多,如页面映射、页面分配、页面回收、页面交换、冷热页面、紧急页面、页面碎片管理、页面缓存、页面统计等,而且对性能也有很高
    的头像 发表于 01-04 09:24 321次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b><b class='flag-5'>内存</b>管理架构解析

    AD5420没有CS引脚是否意味着不能和其他SPI接口的芯片共用SPI总线呢?

    请问一下,AD5420没有CS引脚是否意味着不能和其他SPI接口的芯片共用SPI总线呢?如果必须共用SPI总线有没有什么解决方案呢? 我的电路中将AD7715和AD5420同时连接到MCU的SPI
    发表于 12-15 07:25

    Linux内核内存规整总结

    分配需求,如下图所示: 内存外部碎片导致实际占用物理页不多,但是已无法申请>=4个页连续内存,理想当中我们希望内存没有外部碎片,如下图所示: 内核
    的头像 发表于 11-11 11:17 934次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b><b class='flag-5'>内存</b>规整总结

    Linux 内存管理总结

    一、Linux内存管理概述 Linux内存管理是指对系统内存的分配、释放、映射、管理、交换、压缩等一系列操作的管理。在
    的头像 发表于 11-10 14:58 241次阅读
    <b class='flag-5'>Linux</b> <b class='flag-5'>内存</b>管理总结

    Linux内核内存管理详解

    内存管理的主要工作就是对物理内存进行组织,然后对物理内存的分配和回收。但是Linux引入了虚拟地址的概念。
    发表于 08-31 14:46 425次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>的<b class='flag-5'>内存</b>管理详解

    Linux内核的物理内存组织结构详解

    Linux内存管理子系统使用 节点(node)、区域(zone)和页(page) 三级结构描述物理内存
    发表于 08-21 15:35 245次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>的物理<b class='flag-5'>内存</b>组织结构详解

    C语言malloc申请内存时的碎片问题

    解决问题:malloc在申请内存的时候,内存碎片问题会导致原本内存大小足够,却申请内存失败。
    发表于 08-06 16:58 1009次阅读
    C语言malloc<b class='flag-5'>申请</b><b class='flag-5'>内存</b>时的碎片问题

    Linux内核的作用

    Linux操作系统是当今世界上最为广泛使用的开源操作系统之一,内核则是一个操作系统的核心和灵魂所在。对于一名Linux驱动开发者来说,了解Linux
    发表于 07-06 11:46 1216次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>的作用

    Linux内核内存泄漏怎么办

    Linux内核开发中,Kmemleak是一种用于检测内核内存泄漏的工具。
    发表于 07-04 11:04 591次阅读

    Linux内核实现内存管理的基本概念

    本文概述Linux内核实现内存管理的基本概念,在了解基本概念后,逐步展开介绍实现内存管理的相关技术,后面会分多篇进行介绍。
    发表于 06-23 11:56 522次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>实现<b class='flag-5'>内存</b>管理的基本概念

    Datasheet v1.2更新到v1.4意味着什么?

    38 BOD 静态特性中: 问题:此表从 Datasheet v1.2 更新到 v1.4 意味着什么?这是否意味着不再支持小于 1.75V 的阈值电压 (TRIGLVL)?
    发表于 05-04 07:07

    i.mx8mp是否意味着每个通道都可以支持768KHz/32位?

    在 i.mx8mp RM 文档中,P5944,我对 SAI 容量有些怀疑。 这是否意味着每个通道或通道都可以支持 768KHz/32 位,或者 SAI2/SAI5 模块总共可以支持 768KHz/32 位?
    发表于 05-04 07:04