关闭
搜索
搜索
本版
帖子
用户
热搜:
程序员
简洁模式
高级模式
用户组: 游客
消息
提醒
新听众
我关注的
帖子
道具
勋章
任务
设置
退出
请
登录
后使用快捷导航
没有帐号?
立即注册
设为首页
收藏本站
开启辅助访问
切换到窄版
登录
or
立即注册
快捷导航
搜索
首页
论坛
BBS
MCU单片机技术
程序员交流
Linux内核中用GFP_ATOMIC申请内存究竟意味着什么?
[复制链接]
作者:
诸异道
版块:
›
嵌入式操作系统
›
linux
发布时间:
2021-1-14 15:47:52
1007
0
返回列表
诸异道
当前离线
中级会员
中级会员, 积分 301, 距离下一级还需 199 积分
中级会员
中级会员, 积分 301, 距离下一级还需 199 积分
积分
301
发消息
楼主
电梯直达
诸异道
发表于 2021-1-14 15:47:52
|
只看该作者
|
倒序浏览
|
阅读模式
作者 | 宋宝华 责编 | 张文
来源 | Linux阅码场(ID:LinuxDev)
本文目的:本文补充校正一些 Linux 内核开发者关于 GFP_ATOMIC 的认知不完整的地方,阐述 GFP_ATOMIC 与 free 内存 watermark 的关系,并明确什么时候应该用 GFP_ATOMIC 申请内存。
GFP_ATOMIC vs. GFP_KERNEL
我们都知道,在中断、软中断、spinlock 等原子上下文里面,申请内存,应该使用 GFP_ATOMIC 标记,譬如内核中有大量的 kmalloc/GFP_ATOMIC 的例子:
对于不可睡眠的上下文,如果我们用常规的 GFP_KERNEL 这样的标记去申请内存,可能引发直接的内存 reclaim,从而引起睡眠,所以 GFP_KERNEL 这种标记只适合进程上下文调用:
GFP_KERNEL 的标记可以引发直接的内存回收,从而导致进程阻塞睡眠
,这在原子上下文显然是不允许的。
#defineGFP_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 的一个著名的图。
在 Linux 中,内存有 3 个水位:
HIGH: 系统的 free 内存大于 HIGH 水位的时候,是一个相对保险的值,不需要急着做内存回收(reclaim);
LOW: 系统的 free 内存达到 LOW 水位的时候,启动后台 kswapd 进行内存回收,回收的目标是让空闲内存达到 HIGH 水位;
MIN:系统应该保有的最小 free 内存,当空闲内存达到这个值的时候, kswapd 的后台回收可能来不及了,一般用户在申请内存的时候,进行 DIRECT RECLAIM。
min 水位一般是系统自动换算的,其具体值可以从/proc 看出:
# cat /proc/sys/vm/min_free_kbytes45056而 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 还包含了高优先级的含义:
(__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:
http://lore.kernel.org/linux-mm/1608894171-54174-2-git-send-email-tiantao6@hisilicon.com/
上面 2 个地方,其实都是可以睡眠的进程上下文,但是我们认为在 frontendswap 的路径上,我们对延迟敏感,对 swap 内存过程中进一步引发内存回收也担忧。
因此,这里哪怕是非原子上下文,我们也没有使用 GFP_KERNEL。
点分享点收藏
本帖子中包含更多资源
您需要
登录
才可以下载或查看,没有帐号?
立即注册
收藏
0
相关帖子
•
大多数程序员接触过的技术_负载均衡,但大多数都不知其核心原理
•
产业缺货背景下,STM32峰会都说了什么?
•
Xmanager使用教程:如何在Linux系统上安装Xterm应用
•
超级干货:3个性能监控和优化命令详解
•
开源项目EasyDarwin编译:Linux系统下编译运行最新EasyDarwin的步骤介绍
•
硬核观察|Python之父对Rust、Go、Julia和TypeScript的看法
•
干货|手把手带你搞定4大容器网络问题
•
对话胡伟武:和国产CPU一起突围的20年
•
详细理解Linux虚拟内存
回复
使用道具
举报
返回列表
高级模式
B
Color
Image
Link
Quote
Code
表情
@朋友
您需要登录后才可以回帖
登录
|
立即注册
本版积分规则
发表回复
回帖后跳转到最后一页
浏览过的版块
招聘&找工作
IT业界资讯
快速回复
返回顶部
返回列表