LWN:使用BPF来选择OOM kill的对象!

本文探讨了如何使用BPF(BerkeleyPacketFilter)技术改进Linux内核的内存管理,特别是out-of-memory(OOM)时的进程选择策略。传统的oom_score_adj已不足以满足所有用户需求,ChuyiZhou的BPF补丁提议通过BPF函数定制OOM决策过程,增加了更多灵活性,但引发关于稳定性和实现方法的讨论。

关注了就能看到更多这么棒的文章哦~

Out-of-memory victim selection with BPF

By Jonathan Corbet
August 17, 2023
ChatGPT assisted translation
https://lwn.net/Articles/941614/

默认配置下的 Linux 内核允许进程分配的内存比系统实际可提供的内存更多。这个策略可以更好地利用物理内存,通常情况下也都能达到目的。然而,在某些情况下,内核可能会发现无法提供出来进程认为本已经属于它们的内存。在情况严重时,除了重新启动之外,唯一的解决方法就是宣布内存不够,从而通过终止若干进程来补上这些内存空间。多年来人们付出了很大的努力来制定一些启发式方法,从而挑选出用户可能最不需要的进程。然而很明显,这个解决方案并没有让所有人都满意,因此在不久之前,有人引入了新的方法,使用 BPF 来选择 out-of-memory(OOM)时应该终结的进程。

当内存用尽时,寻找要牺牲的进程有许多方法。比如使用了最多内存的进程就是一个显而易见的选择,但该进程通常是系统中比较重要的组件,例如窗口系统服务器,或数据库管理器(database manager)。因此,多年来,开发人员自然开始试着让内核能够做出更好的选择。可以查看 LWN 内核相关文章的索引,就能看到随着时间的推移,情况发生了那些变化。在当前的内核中,这个决策的核心是一个名为 oom_badness()的函数,该函数会先跳过那些因某种原因而无法终止的进程,然后来进行一些简单的计算。一个进程的“OOM score”值取决于它使用的内存数量,并且经过该进程的 oom_score_adj 值来进行调整。通过调整这些参数,用户空间就可以保护某些进程不被 OOM-killer 杀死,而是让它去杀掉其他一些更应该被 kill 的进程。

然而,对于某些用户来说,这种控制方式显然不够。Chuyi Zhou 的 BPF 补丁系列就是最新的一种希望改进这种控制方式的方案。

在当前的内核中,OOM killer 将遍历所有可能的目标进程,在每个进程上调用 oom_badness(),然后选择分数最高的进程作为目标。Zhou 的 patch set 可以把 oom_badness()检查替换为调用一个 BPF 函数,该函数应该被定义为“fmod_ret” tracing 函数(这意味着它在从内核内部函数返回时被调用,并且可以更改该函数的返回值),它具有以下名称和原型:

int bpf_oom_evaluate_task(struct task_struct *task, struct oom_control *oc);

该函数将在评估每个可能被 kill 对象的一开始时被调用,并且如果它对指定任务做出了决策,就会让正常的评估过程被跳过。oom_control 结构描述了 OOM kill 所发生的上下文;BPF 函数可以访问这个结构,但可能(实际文档上并没有明确写出这个规则)不应对其进行更改。该函数还可以查看正在考虑要 kill 的 task 并最终决定其命运,通过返回值来反映出来:

  • NO_BPF_POLICY:没有对应的策略,也就是应该使用正常的 oom_badness()方法。

  • BPF_EVAL_ABORT:退出这个选择过程,任何一个进程都不 kill。

  • BPF_EVAL_NEXT:跳过当前进程,看下一个。

  • BPF_EVAL_SELECT:选择当前进程为要 kill 的进程。

在返回 BPF_EVAL_SELECT 时,并不意味着就结束了遍历进程列表的过程;如果还有更多需要检查的进程,就会进一步调用 bpf_oom_evaluate_task()。因此,该函数可以改变主意,也就是说如果在后面出现了更应该 kill 的进程的话,就可以再次返回 BPF_EVAL_SELECT。

可以在某些进程中使用 BPF_EVAL_NEXT,同时在其他进程中使用 NO_BPF_POLICY。最终结果将可以保护一些进程免受 OOM(内存不足)killer 的影响,同时让内核按照通常的方式来选择其余进程。然而,混合使用 BPF_EVAL_SELECT 和 NO_BPF_POLICY 看起来可能会产生意想不到的结果,这种组合似乎不是作者期望大家使用的方式,应该尽量避免,除非在将来的版本中有相关更改。

具体而言,oom_control 结构包含了一个名为 chosen 的指针,用于标识当前选中的受害者,以及一个名为 chosen_points 的整数,用于保存其 badness 分数。在没有 BPF 程序的情况下,内核会拿每个进程的分数跟 chosen_points 进行比较,并在新进程的分数较高时来同时更新。如果返回 BPF_EVAL_SELECT,则会设置 chosen 而不设置 chosen_points。如果对于后续有个进程返回了 BPF_NO_POLICY,那么其分数将与一个跟之前选择的进程无关的 chosen_points 进行比较。

此外,这组 patch 还提供了两个相关的 hook。其中一个允许将当前选择受害者的策略的名称存储在内核中;这个名字会在实际执行 kill 时记录到日志中。为了实现这个功能,程序应该定义一个名为 bpf_set_policy_name 的函数:

void bpf_set_policy_name(struct oom_control *oc);

这个函数将在 OOM-kill 过程的一开始时就调用,然后可以调用以下函数:

void set_oom_policy_name(struct oom_control *oc, const char *name, size_t sz);

其中,oc 是传递给 bpf_set_policy_name 的 oom_control 结构,name 是要使用的策略的名字,sz 是该名称的长度。name 限制为 16 字节,包括终止 NUL 字节。

此外,还引入了一个新的 tracepoint,名为 select_bad_process_end,在 OOM-kill 过程无法找到要 kill 的进程时触发。目标是为试图开发新的 OOM-kill 策略的开发人员提供帮助。

这组 patch 目前正在第二次修订。在第一次法布施,内存管理开发者 Michal Hocko 建议简化一下接口。而 Roman Gushchin 则主张采用更通用的方式,也就是在 OOM 时调用一次 BPF 程序,期望它能找到某种方式来释放一些内存。Hocko 回应说最好从一个 "something that is good enough" 开始,后续有必要的话再增加复杂逻辑。在对第二次修订的回应中,Alexei Starovoitov 也支持使用更通用化的 callback,而 Chuyi Zhou 已经开始认真考虑做这种更改会有哪些影响。

Hocko 和 Gushchin 都表示担心将 BPF 引入这段在系统处于紧急状态时运行的代码可能会进一步降低内存不足情况下的稳定性。例如,尝试在这种情况下分配大量内存的 BPF 程序可能就会出现问题。然而,任何 hook 到 OOM-killer 的代码都有这个问题,而不是 BPF 方案特有的问题。

这次讨论显示出,使用 BPF 来选择 OOM-killer 的受害者这个方案挺有吸引力。然而,到目前为止,关于这项工作所应采取的实现方法尚无明确共识。因此,在进入 mainline 之前很可能还会看到这个功能经历一些重大变化;在那之前,内核将不得不继续以传统方式来选择要牺牲的进程。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

format,png

代码转载自:https://pan.quark.cn/s/a4b39357ea24 粒子群优化算法(Particle Swarm Optimization, PSO)是一种借鉴群体智能理念的优化方法,其理论基础源于对自然界中鸟群或鱼群群体行为的观察与分析。该算法通过模仿群体内各粒子在解空间中的运动轨迹来探寻最优解,因此在处理各类复杂的优化任务时具有广泛的应用价值,包括但不限于函数最大值与最小值的求解。 在粒子群优化算法的框架内,每一个粒子象征着一个可能的解决方案,而粒子的位置坐标与速度矢量构成了算法的核心参数。粒子的位置具体表示解空间中的一个坐标点,而速度则决定了粒子在解空间内移动的方向与幅度。该算法的执行过程主要包含两个核心环节:即局部最优(个体最优位置)与全局最优(全局最优位置)的动态更新。 1. **初始设定**: 随机产生一组粒子的初始位置和速度值,这些初始值通常设定在函数定义域的搜索范围内。 2. **适应度评价**: 计算每个粒子的适应度水平,即目标函数在当前粒子位置处的取值。若目标是寻找函数的最大值,则适应度值直接为函数值;若目标是寻找最小值,则适应度值取为函数值的负数。 3. **个体最优位置更新**: 当当前粒子的适应度水平优于其历史记录中的最优位置时,则对该粒子的个体最优位置进行修正。 4. **全局最优位置更新**: 在所有粒子完成个体最优位置的更新后,通过比较各粒子的个体最优位置,选取适应度值最大(针对最大值问题)或最小(针对最小值问题)的粒子作为全局最优位置。 5. **速度与位置调整**: 基于当前的粒子速度与位置,以及个体最优位置和全局最优位置,对每个粒子的速度和位置进行重新计算。速度的更新公式通常表达为: \[ v_{ij}(...
代码下载地址: https://pan.quark.cn/s/879ea47e17cf 在信息技术领域中,前端构建过程中常常面临页面间互动的挑战,诸如信息流转和函数执行等问题。EasyUI作为一个基于jQuery的界面开发工具包,具备大量可用的构建模块,其中包括用于生成弹出式界面(window)的特定功能。在EasyUI的应用中,可能会出现需要在弹出式界面(次级页面)与主页面之间实现数据交换或执行主页面函数的情况。下文将深入阐释这一流程。 让我们深入探究标题所提及的“弹出window窗口数据交互”。在EasyUI环境中,构建一个弹出式界面通常遵循以下步骤: 1. 构建一个HTML文档作为次级页面,其中应包含需要呈现的信息和互动组件。 2. 在主页面中,借助`$.dialog`或`$.window`函数打开次级页面,同时可以设定若干参数,例如界面宽度和高度、内容链接地址等。 例如: ```javascript $.window({ title: 次级界面, width: 500, height: 400, href: subPage.html, onClose: function () { // 在窗口关闭时执行的回调操作,可用于处理关闭事件逻辑 } }); ``` 3. 向次级页面传递数据:可以在`href`属性值中借助查询参数传递基础数据。例如: ```javascript href: subPage.html?parentId=123 ``` 在次级页面中,可以通过`window.location.search`属性获取查询参数并加以解析。 然后,我们将探讨“调用主页面函数”的操作。EasyUI提供了一种途径,借助`parent`关键字来引用主窗口的对象,进...
打开链接下载源码: https://pan.quark.cn/s/a4b39357ea24 在Java编程环境中,将16进制的四字节数据转换为浮点数是一项常见的数据处理任务,特别是在与硬件设备进行交互或执行底层通信时。 这一过程涉及到对字节顺序的掌握,以及Java语言中的数据类型转换。 以下是针对这一主题的深入阐述。 16进制是一种数值表示形式,其中每四个字符对应一个字节(即8位)。 浮点数在计算机内部通常以二进制格式存储,具体分为符号位、指数部分和尾数部分三个组成部分。 在Java语言中,浮点数主要有两种类型:单精度浮点数(float)和双精度浮点数(double),它们分别占用32位和64位存储空间。 1. **字节序**:在进行16进制到浮点数的转换时,必须关注字节序,即字节在内存中的排列方式。 存在两种字节序:小端字节序(Little Endian)和大端字节序(Big Endian)。 小端字节序的特点是最低有效字节位于最低地址,而大端字节序则是指最高有效字节位于最低地址。 Java语言中的默认字节序为网络字节序,即大端字节序。 2. **解析流程**:将16进制字符串转换为浮点数,通常包括以下步骤: - 将16进制字符串转化为字节数组,每个16进制字符对应一个字节。 - 根据字节序调整字节数组的排列顺序。 - 运用`Float.intBitsToFloat()`方法将字节数组转换为整数,随后将此整数转化为浮点数。 这是因为在计算机内存中,浮点数是以整数形式存储的,通过特定的位运算可以实现转换。 3. **代码实例**:以下是一个简单的Java方法,展示了如何执行这一转换: ```java public float hexToFloat(String hexStr) { by...
【重要提示】本资源设置为0积分下载,若非0积分请勿轻易下载 亲爱的CSDN用户: 首先感谢你点进这个资源页面。我需要提前说明一个重要情况: **本资源原本已设置为“0积分下载”**,即作者希望完全免费共享。但CSDN平台有时会根据文件的下载热度、文件大小、用户权限等因素,**自动将部分资源的积分调整为非0数值**(如1积分、2积分、5积分等)。这是平台系统的自动行为,而非作者本人的设定。 **因此,如果你当前看到该资源的下载所需积分不是0(例如显示为1、2、3……),请谨慎决定是否下载。** 如果你按照非0积分支付并下载后发现资源内容不符合预期、链接失效,或者实际上该资源本应是免费的,作者无法为此承担积分损失或退还操作。**强烈建议:仅在页面显示为0积分时进行下载。** 另外,本资源描述中**并未直接提供具体的下载地址或外部链接**,因为它本身是一个通过CSDN官方上传通道提交的文件/内容包。如果你看到描述中没有外部网盘地址,这是正常的——资源文件应通过CSDN内置的“下载”按钮获取。若因平台积分显示异常导致你支付了积分,请优先联系CSDN客服咨询积分退还政策,作者没有权限修改平台自动设定的积分值。 感谢你的理解与支持。技术分享本应开放,但受限于平台规则,特此提醒如上。祝学习进步!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值