本文目的

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

1. GFP_ATOMIC vs. GFP_KERNEL

2. 内存水位,PF_MEMALLOC和GFP_ATOMIC

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

GFP_ATOMIC vs. GFP_KERNEL

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

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

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过来:

在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就设置了这个标记,这个代码里面的注释也非常精彩:

如果我们不允许回收内存的代码申请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:

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

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

一个patch的例子

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

  • 原子上下文使用GFP_ATOMIC

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

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

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

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

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

(END)

更多精彩,尽在"Linux阅码场",扫描下方二维码关注

宋宝华:Linux内核中用GFP_ATOMIC申请内存究竟意味着什么?相关推荐

  1. Linux 内核中用 GFP_ATOMIC 申请内存究竟意味着什么?

    作者 | 宋宝华  责编 | 张文 头图 | CSDN 下载自东方 IC 来源 | Linux阅码场(ID:LinuxDev) 本文目的:本文补充校正一些 Linux 内核开发者关于 GFP_ATOM ...

  2. 宋宝华- Linux namespace - Docker 背后的故事

    名称空间是在OS之上实现容器与主机隔离,以及容器之间互相隔离的Linux内核核心技术.根据<Docker 最初的2小时(Docker从入门到入门)>一文,名称空间本质上就是在不同的工作组里 ...

  3. 宋宝华:世上最好的共享内存(Linux共享内存最透彻的一篇)上集

    共享单车.共享充电宝.共享雨伞,世间的共享有千万种,而我独爱共享内存. 早期的共享内存,着重于强调把同一片内存,map到多个进程的虚拟地址空间(在相应进程找到一个VMA区域),以便于CPU可以在各个进 ...

  4. 宋宝华Linux培训笔记-Linux进程管理

    1.cpu进程状态 linux中进程状态如下图: 浅度睡眠为进程等待资源或中断响应,即使资源没有拿到也可以被唤醒:深度睡眠为进程等待资源,拿到资源后进入就绪状态. 僵死状态为进程死亡,但还没有被父进程 ...

  5. 宋宝华Linux培训笔记-Linux多线程

    1.POSIX标准多线程 发送给进程下一组线程的信号将被共享,被其中任意一个线程处理.同一进程创建的线程同生死,如果收到一个kill信号,这一组task_struce都会退出. 2.NPTL模型 内核 ...

  6. linux pdf 宋宝华,51CTO博客-专业IT技术博客创作平台-技术成就梦想

    原创 宋宝华 Linux阅码场 2018-04-10 前言 网上关于BIO和块设备读写流程的文章何止千万,但是能够让你彻底读懂读明白的文章实在难找,可以说是越读越糊涂! 我曾经跨过山和大海 也穿过人山 ...

  7. 宋宝华:论一切都是文件之匿名inode

    01 唯有文件得人心 当一个女生让你替她抓100只萤火虫,她一定不是为了折磨你,而是因为她爱上了你.当你们之间经历了无数的恩恩怨怨和彼此伤害,她再次让你替她抓100只萤火虫,那一定是因为她还爱着你. ...

  8. 宋宝华: 关于DMA ZONE和dma alloc coherent若干误解的彻底澄清

    原创 宋宝华 Linux阅码场 2018-01-22 作者简介 宋宝华,他有10几年的Linux开发经验.他长期在大型企业担任一线工程师和系统架构师,编写大量的Linux代码,并负责在gerrit上r ...

  9. 宋宝华:评Linux 5.13内核

    目录 Misc cgroup Landlock安全模块 系统调用的堆栈随机化 printk无锁ringbuffer的进一步优化 BPF可调用内核函数 公共的IO PAGE Fault支持 Linux ...

最新文章

  1. 线上讲座丨罗杰:前沿——NISQ时代下的工程超导量子计算机
  2. c语言中栈区运用原理形象图,C语言实现使用动态数组来构造栈结构
  3. 怎么自学python自动化测试-python自动化测试如何自动生成测试用例?
  4. 添加列属性_css多列属性
  5. leetcode142. 环形链表 II
  6. 【Oracle】append
  7. LinkedHashMap 底层分析
  8. 抓取必应在线词典的英语音标
  9. DiskFileUpload上传文件并获取前端表单数据
  10. c2c运营流程图_电商运营流程图模板分享,运营的核心都在这里了,快来拿走吧...
  11. STM32CubeMX | 37 - 使用RS485总线进行双板通信(SP3485)
  12. JSP基础之网站用户管理
  13. 【多式联运】基于模拟退火优化遗传算法求解多式联运运输问题(含碳政策)含Matlab代码
  14. [C程序设计]请编程序将“China”译成密码,密码规律是:用原来的字母后面第4个字母代替原来的字母。
  15. 马云:阿里巴巴的最高机密是我们的组织架构图
  16. Air780E小程序远程开关-LuatOS版本
  17. 【Win7系统中怎么在我的电脑里面找回摄像头设置】
  18. 麦当劳一“发币”,币圈就闹笑话,加密数字货币到底是什么?
  19. SharePoint Keyword Query Languge(KQL)语法
  20. 我是如何诱骗你的-高级钓鱼技术

热门文章

  1. Python线程和进程的了解,多线程多进程
  2. 远景(智能/能源/动力)2023秋招提前批!内推啦
  3. python 如何同时遍历两个列表
  4. [Android]桌面应用
  5. 博主文章导航(分门别类,实时更新,永久置顶)
  6. AI综述专栏 | 朱松纯教授浅谈人工智能:现状、任务、构架与统一
  7. 《学习之道》第六章一心多用
  8. 赛普拉斯CYpress,初接触之一电磁感应触摸按键demo
  9. 曾仕强经典语录-《易经的智慧》
  10. Linux学习笔记:联想拯救者Y7000进BIOS