LWN:BPF allocator 碰到麻烦了!

bpf的了解以及bpftrace的简单练习 使用ebpf可以实现的功能打开新世界,可以不改变源码的情况下,实现内存,网络,对应接口等各种期望内容的监控。可以使用bpf直接进行开发,使用clang编译成ebpf字节序后加载进行使用。使用bcc进行开发实现功能,多是python/lua,对应的demo可以参考githuab.使用bpftool工具集可以进行加载,查看,卸载等一系列的功能,没有过多研究。 阅读详情

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

The BPF allocator runs into trouble

By Jonathan Corbet
April 29, 2022
DeepL assisted translation
https://lwn.net/Articles/892743/

5.18 内核合并的一个改动是为已经加载到内核里的 BPF 程序提供一个专门的内存分配器(memory allocator)。不过在那之后,这个功能遇到了相当多的困难,几乎可以肯定在 5.18 的最终版本中会被禁用。走到这一步,部分原因在于分配器本身的 bug,但是这项工作也很不幸地引发了内核的内存管理子系统中一些更古老、隐藏更深的 bug。

在目前的内核中,BPF 程序的内存空间(经过 JIT 代码转换之后)的分配代码,就是用为 loadable module 分配内存的那些代码来分配的。这看起来很有道理,因为两种情况都是要申请空间用于在内核中运行的可执行代码。但是,这两种使用场景之间有一个关键区别。内核 module 是相对静态的,它们一旦被加载就几乎不会被删除。相反,BPF 程序可以频繁地出现和消失。在系统生命周期中可能有成千上万次的加载和卸载动作。

这一差异目前看来影响很大。可执行代码的内存必然要设置执行权限(execute permission),因此也必须是只读的。这就要求这部分内存在 page table 中有自己的 mapping,也就意味着它必须从内核的 direct mapping(可能是 huge-page 方式管理的)中分离出来。这就要把 direct mapping 分解成更小的 page。随着时间的推移,就会让 direct map 越来越碎片化,可能会对性能产生明显的影响。BPF 分配器的主要目标是将这些分配动作都采用一组专用的 huge page 中,避免产生这种碎片化。

不过,在这段代码合并后不久,就开始涌现出一些 regression 问题报告,以及相关的担忧。这引起了 Linus Torvalds 和其他开发者的注意,并揭示了一系列的问题。虽然其中一些 bug 是在 BPF 分配器本身,但最具破坏性的问题是在另一个子系统(vmalloc()分配器)中以前做出的一个改动。

vmalloc() and huge pages

vmalloc()(及其多种变种函数)与其他的内核内存分配接口的差异在于,它返回的内存虚拟地址连续,但物理上可能是分散的。因此,它适合于分配较大的、并且不需要物理连续的内存区域。由于 vmalloc() 的开销较大,而且 32 位系统的可用地址空间不足,人们曾经不希望大量使用 vmalloc(),但是随着时间的推移,人们的态度已经发生了变化。现在,使用 vmalloc()作为一种避免进行较大 size 分配时因内存碎片化而失败的方法在普遍使用了。近年来,像 kvmalloc() 这样的函数也被添加进来,它将在普通分配未能成功时自动退回到 vmalloc()。

在 2021 年,Nick Piggin 增强了 vmalloc()的功能,如果申请的 size 足够大,就可以分配 huge page 了。人们可能会想为什么需要这样做,毕竟 vmalloc() 明确是为了不需要物理连续的内存分配而设计的。答案就是 huge page 可以通过减少对 CPU 的 translation lookaside buffer (TLB)的压力来提升性能。内核有一些大 size 的分配场景可以从这个改动中受益,所以它被合并到了 5.13 内核中。

哪怕在合入的时候,人们也提出了一些注意事项。内核中有些地方会因为收到 vmalloc() 调用返回的 huge page 而无法正常使用。比如说 PowerPC module loader。所以 Piggin 也添加了一个 flag VM_NO_HUGE_VMAP,它要求只使用 base page。当然,vmalloc() 不接受任何 flag,所以要想避免分配到 huge page 的话,只能通过更底层的 __vmalloc_node_range() 函数来分配了,直到 5.13 周期的后期添加 vmalloc_no_huge() 为止。当时 x86 架构也没有启用 Huge-page 分配,因为没有人去花时间寻找并解决那里的潜在问题。

BPF-allocator 系列的第一个 patch 在 vmalloc()中启用了 x86 架构的 huge page 分配;这对 BPF 分配器来说是有必要的,因为需要使用 huge page。这一切看起来都很好,直到开始了更广泛的测试,就发现了问题。看来在 x86 上启用 vmalloc() 中的 huge page 可能不是一个好主意。不过其实这个问题实际上与 x86 架构本身并没有什么关系。

当 vmalloc()(正如它在 5.18 周期开始时的行为)在响应一个申请分配 huge page 的请求时,会返回一个 compound page——这是一组连续的 base page,表现得像一个单一的、更大的 page 而已。这些 page 的组织方式是有差异的,其中关于它要如何使用的大部分信息,都存储在第一个 base page ("head")的 page structure 中。接下来的那些("tail")page 的 page structure 大多只包含了一个指向 head page 的指针。务必注意不要把 tail page 当作是独立页面,否则会出现问题。

问题就这么发生了。事实证明,内核里面有很多代码都是假定可以直接将来自 vmalloc() 的内存视为由 base page 组成的;这种代码会调整这个 page structure 而没有注意到它可能正在处理的是 tail page。这导致了系统内存 mapping 损坏,一旦检测到这种 mapping 损坏,内核就会出现 oops。一个已知会发生这种情况的案例是 Rick Edgecombe 首先注意到的,即驱动代码调用 vmalloc_to_page() 来获取 vmalloc() 分配中的某个 page structure(因此,可能在一个 compound page 的中间位置)。事实证明,有相当多的驱动程序使用 vmalloc_to_page()。如果相关内存是由 compound page 组成的,那么每一个驱动程序几乎都会碰到问题。

这个具体问题最终被 Piggin 修复了。现在的代码是将分配的 huge page 分割成 base page(同时保留 huge page mapping),不再使用 tail page。但是在 vmalloc() 子系统中还潜伏着一些其他的问题,随着越来越多暴露出来,Torvalds 得出结论:"HUGE_VMALLOC 的设计有严重的错误"。他说,从一开始的设计就有问题,问题现在才出现,是因为在 x86 架构上启用该功能导致了更广泛的测试。

Resolutions for 5.18

Piggins 的 fix 被合并到 5.18-rc4 prepatch 中。与此同时,BPF 分配器 patch 的作者 Song Liu 正在努力寻找一套解决方案,从而能安全地使用该分配器,于是就产生了一组由四个 patch 组成的方案。

  1. 删除了 VM_NO_HUGE_VMAP flag,改用新的 VM_ALLOW_HUGE_VMAP 这个变种。这改变了该 flag 的含义,从而让 huge page 分配成为一个可以要求使用的功能,而不是要求禁止的。

  2. 让 alloc_large_system_hash() (用于为大型哈希表来分配空间)来优先使用 huge page 分配,因为这里使用是肯定安全的。

  3. 增加了一个名为 module_alloc_huge() 的函数,它也能实现 huge-page 的分配。

  4. 使用 module_alloc_huge() 来分配 BPF 分配器所使用的空间。

如果在 vmalloc()中广泛使用了 huge page 是唯一的问题,那么这些措施可能已经足够了。然而,Torvalds 也不喜欢他在 BPF 分配器代码中看到的一些内容。其中之一是,它在没有初始化内存的情况下就启用了所分配的内存的可执行权限,这就给内核的地址空间里增加了一堆随机的可执行代码段。他总结说 "我真的不认为这已经准备好大规模使用了"。

因此,他决定只合入 Liu 的第一个 patch,也就是完全禁用 vmalloc()中的 huge page 分配(因为还没有什么地方使用了新的 opt-in 方式的 flag)。最初他打算到此为止,但后来判定第二个 patch 也可以安全地合入。然后他甚至更进一步添加了一个他自己的 patch,在 kvmalloc() 中实现了 huge page 分配。这样做的理由是,从该函数返回的内存可能来自一个 slab 分配器,所以拿到这块内存的用户无论如何都不应该对相应的 page structure 使用底层操作技巧。

此后,Liu 在另一组 patch 中修复了未初始化内存的问题。BPF 维护者 Alexei Starovoitov 试图说明这项工作也应该被合入,使 BPF 分配器在 5.18 版本中可用。不过 Torvalds 仍然未被说服,所以这项工作似乎更有可能是 5.19(甚至可能是更晚)才会合入了。也就是说 BPF 用户可能只需要再等一个发布周期就可以使用专门的内存分配器了。

从这个小插曲中可以得出一些结论。调整底层的内存管理特性是很棘手的,可能会在出人意料的地方产生问题。更为流行的架构所带来的广泛测试有很大的价值,它会发现那些在用户基数较小的架构上可能被隐藏起来的错误。但是,也许最重要的是,它说明了在内存管理子系统之外就不应该去访问 page structure。将这种底层的细节暴露在整个内核中,总是会导致这种意外发生。让内核的其他部分不再使用 page structure(这才刚刚开始)将是一个漫长而困难的任务,但还是很值得去承受这些辛苦的。

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

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

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

306f9b0a7eda81bae978f415514a5c4e.png

python抓包 -- 用wireshark抓包、解析--scapy、PyShark 只捕获源地址为192.168.1.125且目的端口为80的流量:src host 192.168.1.125 && dst port 80。prn: 定义回调函数,使用lambda表达式来写回调函数(当符合filter的流量被捕获时,就会执行回调函数)只捕获某个MAC地址主机的交互流量:ether src host 00:87:df:98:65:d8。只捕获来源于某一IP的主机流量:src host 192.168.1.125。只捕获除80端口以外的其他端口流量:!只捕获80端口的流量:port 80。 阅读详情

相关推荐

[ensp报错:USG6000V错误代码45解决方案]

[ensp报错:USG6000V:错误代码45解决] [ensp报错:USG6000V:错误代码45解决] 第一种处理方式: ensp的45错误帮助文档里的解决方法:(这里就不说了,上华为爸爸的图) ensp的45错误:如果你的45错误不是描述的那个,可能是ensp与virtualbox不兼容了。 错误描述:具体表现为在virtualbox里没有vfw_usg的条目,虚拟介质管理器里也没有相应的条目: 就是vfw_usg_vdi这个 这种情况下你把ensp卸载重装多少次都没用,原因在两个软件的兼容

weixin_45456536的博客 3万+

linux内核态hook模块

linux内核支持动态加载module,今天不聊正常的module,只简单看一下实现Hook的module. hook通常翻译做劫持,不过这个翻译听起来让人不舒服,感觉有点恐怖,所以大家都是喊行话:hook. 上图是经典的堆栈式hook,也是splice典型的做法,在原有的流程中插入hook,更加典型的做法是栈在调用过程中从funcA->funcB变成了funcA->hook-&gt...

faxiang1230的专栏 4571

OSMDroid(1)——OSM简介,基础例子搭建

1.OSMDroid简介 Osmdroid是一款完全开源的地图基本操作SDK,相比于现在普遍使用的百度地图,高德地图,谷歌地图等最大的好处就是开源。 最近在做一个军方项目,要求完全不能联网,从开发到应用整个阶段都是在局域网进行,相比之下采用了OSMDroid这个SDK作为解决方案。 先来看OSMDroid,便是(OpenStreetMapForAndroid),后面都简称OSM...

robotskly的博客 6177

“人生苦短,我用Python“——网络嗅探与欺骗

如果想要彻底了解一个网络,那么最好的办法就是对网络中的流量进行嗅探。此篇记录几个嗅探工具,这些嗅探工具可以用来窃取网络中明文传输的密码,监视网络中的数据流向,甚至可以收集远程登录所使用的NTLM数据包(这个数据包中包含登录用的用户名和使用Hash加密的密码)。详见《python渗透测试编程》。

weixin_42902126的博客 1177

嵌入式:简单的service框架

在嵌入式中,我们获取一个资源、设置一个变量、更新数据的话最直接的方式就是直接调用一个函数。这样的写法也可以满足基本的功能,前提是这个系统是只要一个任务,只有一个while(1)如图1.1。图1.1当有两个或者两个以上的任务的时候,同时调用一个函数(设置一个状态值、操作同一个资源、操作指针等行为)的流程如图1.2。图1.2当两个任务同时操作一个资源的时候,就会有重入的问题,会导致想不到的异常问题(数据不对、指针异常等)。

stupid的博客 986

【交易系统系列27】带你看懂订单的“奇幻漂流”

作为一个在交易所后台“厨房”里摸爬滚打了十多年的老兵,我将用一杯手冲咖啡的时间,带你亲历一次完整的订单“奇幻漂流”。本文将用一个“奶爸”的生活视角,硬核拆解**撮合(Matching)**、**清算(Clearing)**、**结算(Settlement)**和**出入金**这四大核心环节。这不仅是一次对**交易系统优化**和**撮合引擎架构**的深度剖析,更是一场关于传统金融与数字金融两种不同“上菜”哲学的真实故事。

weixin_43988453的博客 406

Python3上BPF学习-读取DNS事件

Python3上的BPF学习

wq897387的专栏 529

第二十一:Python接口自动化-处理Json数据

【代码】第二十一:Python接口自动化-处理Json数据。

欢迎来到本博客! 111

CONFIG_ARM64_MODULE_PLTS 的作用

在模块加载的时候会调用module_alloc,从这个函数中可以看到,如果没有使能CONFIG_ARM64_MODULE_PLTS。 模块只能使用128M的MODULES_VSIZE,如果是能了CONFIG_ARM64_MODULE_PLTS 且没有使能CONFIG_KASAN 的时候 在128M 不够用的时候,将模块申请的size的范围拓展到2G void *module_alloc(unsigned long size) { u64 module_alloc_end = module_alloc_.

jason的笔记 1581

第三天:Python基础语法详解

Python代码规范与注释最佳实践 摘要: 本文深度解析Python缩进规则与代码结构的技术规范,包括缩进的底层原理、语法规则和错误处理。详细阐述Python注释系统,涵盖行内注释、文档字符串和类型注释等多种形式,并提供工业级代码组织方案。研究显示,良好的缩进可提升40%的代码识别速度,降低50%的认知负荷。文章还对比了Sphinx、pdoc等主流文档生成工具,给出企业级项目中的注释编写原则和模板建议,帮助开发者构建更可维护的Python代码。

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 1010

题解:洛谷 P14357 [CSP-J 2025] 拼数

等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。小 R 想知道,在他所有能拼成的正整数中,最大的是多少。你需要帮助小 R 求出他能拼成的正整数的最大值。小 X 给了小 R 一个字符串。输出一行一个正整数,表示小 R 能拼成的正整数的最大值。中的任意多个数字,按任意顺序拼成一个正整数。,表示小 X 给小 R 的字符串。#普及-# #其他排序#洛谷:[P14357。

团爸讲算法 1394

抓住被恶意隐藏的Linux内核模块

前面的文章介绍了一种相对彻底的隐藏Linux内核模块的方法: https://blog.youkuaiyun.com/dog250/article/details/106023941 总结下来就是: 摘除list,使得/proc/modules中不可见。 摘除kobject,使得/sys/modules/中不可见。 摘除depend on,使得依赖模块的/sys/modules/$(depended)/holder/中不可见。 摘除vmap area list/rbtree,使得/proc/vmallocinfo中不

TCP/IP 6060

C# 开发实战:深度解析 13.56MHz 射频卡读写应用

本文详细介绍了如何在 C# 环境下开发 13.56MHz 射频卡的读写应用。通过 ACR122U 作为硬件设备,结合 C# 提供的 COM 组件或 SDK,我们能够实现对射频卡的读取与写入功能。在实际开发中,开发者还需要根据具体应用场景选择合适的卡片类型与设备,并注意性能优化和异常处理。随着技术的发展,RFID 技术的应用场景会越来越广泛,开发者可以根据不同需求,灵活扩展读写功能,实现更加智能化和自动化的系统。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1600

LWN:BPF专用的内存分配器!

关注了就能看到更多这么棒的文章哦~A BPF-specific memory allocatorBy Jonathan CorbetJune 30, 2022DeepL assisted translationhttps://lwn.net/Articles/899274/内核现在并不缺内存分配器(memory allocator),所以人们可能不理解为什么又要加一个分配...

Linux News搬运工 388

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

LWN:针对BPF代码的内存分配器!

关注了就能看到更多这么棒的文章哦~A memory allocator for BPF codeBy Jonathan CorbetFebruary 4, 2022DeepL assist...

Linux News搬运工 388

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

LWN:slab 分配器的sheaves以及任意上下文的分配功能!

总而言之,他说,来自 sheaves 层的初步结果是 promising(很有希望的),但它与 slab 调试的交互需要改进。(它是 slab 分配器的一部分)实现的工作会议,该版本期望可以从任何上下文中的 BPF 程序中调用。Hoang Nhat Pham 同意,他说他工作的系统具有大量的 CPU,但只有一个 NUMA 节点,从而导致大量的锁竞争,而 per-CPU 缓存可以改善这种情况。最后一个特性几乎是没有额外代价的,因为幸运的是,当请求到达时,分配器会有一个具有足够对象的 sheaf 存在。

Linux News搬运工 1708

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

LWN:针对可执行代码的另一个内存分配方案!

关注了就能看到更多这么棒的文章哦~Yet another memory allocator for executable codeBy Jonathan CorbetJune 8, 2023DeepL assisted translationhttps://lwn.net/Articles/933867/内核的代码越来越动态了,也就是随时会出现新的 text 段代码。目前,为新内核代码分配内存的责...

Linux News搬运工 1110

LWN:6.11合并窗口的剩余部分!

关注了就能看到更多这么棒的文章哦~The rest of the 6.11 merge windowBy Jonathan CorbetJuly 29, 2024Gemini-1.5-flash translationhttps://lwn.net/Articles/982605/6.11-rc1版本的发布标志着 6.11 合并窗口于 7 月 28 日结束。当时有 12,102 个非合并变更集(...

Linux News搬运工 2366

arm linux 内存分布总结

转自:http://blog.youkuaiyun.com/xiaojsj111/article/details/11724081上图是linux的arm的虚拟地址分布总览,我们按从低地址到高地址的顺序逐个描述,每项的描述包括如下的内容的组和:地址范围大小,虚拟转物理的接口函数,各个区域对应的分配函数,该区域有什么作用,使用场合等等。首先开始第一个区域:CPUvector page null pointer

大海蓝天的专栏 5234

linux - 内存 - KO占用

【代码】linux 内存 - KO内存占用。

qazw9600的专栏 1785

通过bcc 使用ebpf

通过前一篇博文知道要使用ebpf debug kernel还是相当麻烦的,github 上有个项目 https://github.com/iovisor/bcc 可以简化ebpf的操作,应为kernel space已经支持ebpf,所以这个项目主要集中在user space部分的编写,user space 可以通过各种语言编写,这里以python为例. 下面的代码的是在调用sys_clone的

jason的笔记 3240

linux arm的高端内存映射

与高端映射对立的是低端映射或所谓直接映射,内核中有关变量定义它们的它们的分界点,全局变量high_memory,该变量定义在mm/memory.c文件中(存在MMU的前提下),可见不区分体系结构,对于当前我手头的marvell的arm设备即对于arm体系结构,high_memory在初始化阶段的创建内存页表时初始化值,它的值就是:物理内存最后一个node的末尾,比如物理内存只有一个node,大小是

cosmoslhf的专栏 5210

再谈内核模块加载(二)—模块加载流程(上)

内核模块加载一共有两个syscall入口,分别为: * sys_init_module: 用户态传入包含模块代码的内存地址 * sys_finit_module: 用户态传入模块二进制的文件句柄fd 除了以上区别外,sys_fini_module接口相对更加灵活,其可以传入额外的flag来忽略模块版本信息和CRC以强制加载。二者最终都直接 return load_module函数,真正的模块加载是在load_module函数中完成的,其声明如下: static int load_mod...

ashimida 5000

一文搞清楚linux系统内存详情:buffer/cache等

前言 我们都知道,free命令可以查看linux系统里的内存使用情况: 但是这个粒度比较粗,对实际的内存问题的调试,帮助并不大。我们在开发或者调试问题的过程中,有时候需要掌握更细粒度的系统内存的详细的使用情况,这个时候/proc/meminfo的输出内容就派上用场了。通过它的输出信息,我们可以: 清晰地知道系统中的内存瓶颈究竟在哪里?(毕竟内核里面使用内存的单元太多了) 内存是被块设备的IO,也就是Buffer给占用了,还是被Cache给占用了? 如果是被Cache给占了,具体是被shar

iqifenxia的博客 2470

python bcc运算_顶部5:学习Python,使用bcc / BPF分析Linux性能,等等

python bcc运算 本周,我们来看一下七个用于分析Linux性能的工具,关于Apache Solr进行机器学习的简介,Linux供应商固件服务如何使更新更容易,Jen Krieger所学的使LEGO块发光的10件事以及学习Python的五种方法。 前5个帖子 5. 7种使用bcc / BPF在Linux中分析性能的工具 Netflix的高级性能架构师Brendan Greg...

cumo3681的博客 728

BPF(BSD Packet Filter)

源地址: BPF(BSD Packet Filter)--应用和理念扩展 BPF是一个过滤机制,它用于过滤送往特定地点比如用户空间的数据包,它被设计成一种类似汇编语言的语言,可以称之为伪汇编码。虽然被设计用来过滤数据包,但这种设计方式更适合用于操作硬件,特别用来编写需要写少量固定序列的硬件驱动程序。不管用于什么,BPF的设计是优秀的,是状态机实现控制逻辑的完美实例。BPF实际上是一组基于状态机的...

RToax 1909
上一篇: LWN:2022 Linux存储、文件系统、内存管理以及BPF峰会!
下一篇: LWN: printbuf 暂时遇到了困难!
LinuxNews搬运工
博客等级 码龄7年 438粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值