[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f8OilvUJhwTbJ3q2RwtXohNiee5cVhmVBI0Dldzv1u_M":3},{"item":4,"related":44},{"id":5,"type":6,"title":7,"slug":8,"summary":9,"body":10,"coverUrl":11,"productScreenshots":12,"productLinks":13,"authorName":14,"authorUrl":15,"authorSubject":16,"category":17,"tags":22,"sourceLabel":35,"sourceName":35,"sourceUrl":36,"status":37,"seoTitle":7,"seoDescription":9,"canonicalUrl":38,"isFeatured":39,"sno":40,"sortOrder":41,"publishedAt":42,"updatedAt":43,"createdAt":43},"292b95b6-50fd-4f7b-b590-491fbc208531","article","BPF CO-RE：一份 eBPF 程序怎样适配不同 Linux 内核？","ebpf-core-portable-kernel-relocations","BPF CO-RE 借助 BTF 类型信息和加载时重定位，减少 eBPF 程序因内核结构变化而反复编译的负担。本文解释它搬动的是哪些“结构偏移”，以及为什么 CO-RE 不等于任何内核、任何机器都能直接运行。","eBPF 程序常常需要读取内核中的数据结构，例如进程、网络包或调度信息。但 Linux 内核会随着版本、配置和架构变化调整结构布局：字段可能移动，类型也可能发生变化。若程序把字段偏移写死，换一台机器或升级内核就可能读错位置。BPF CO-RE 的目标，是让这类程序少一些“每台机器重新编译”的负担。\n\n## 编译时留下可调整的线索\n\nCO-RE 是 Compile Once – Run Everywhere 的缩写。它依赖 BTF（BPF Type Format）等类型信息：目标内核提供自身类型和字段布局的描述；编译出来的 eBPF 对象则包含重定位记录，指出程序依赖了哪些类型或字段。加载器读取目标内核的 BTF，再把这些记录调整为该内核实际的布局。\n\n可以把它想成一份可以自动校正的地图。程序不只记下“目标字段在第 24 个字节”，而是留下“我要访问这个类型里的这个字段”的语义线索。运行前，加载器对照目标内核的类型地图，重新计算访问位置。Linux 的 BPF LLVM 重定位文档展示了对象文件如何记录符号和偏移，以及加载时为何需要解析这些重定位。\n\n## “一次编译”仍有适用边界\n\nCO-RE 解决的是一类重要的布局变化问题，并不意味着任意 eBPF 程序都能在所有 Linux 系统上工作。目标内核需要提供合适的 BTF 信息；程序使用的 helper、kfunc、挂载点、权限和配置也必须存在。架构差异、内核功能差异或安全策略限制，仍可能导致加载失败，或者要求开发者提供不同实现路径。\n\n另外，CO-RE 不会替程序验证逻辑正确性。字段偏移被正确重定位，只说明程序更可能读到预期字段，不代表数据语义、并发时序或边界检查都没有问题。读取内核数据仍要遵循 verifier 的安全约束，加载流程也需要适当权限。\n\n它的价值在于把“字段在哪儿”从编译时硬编码，改为加载时根据类型信息适配。对可观测性工具、网络诊断和系统分析程序来说，这能显著降低维护成本。理解 CO-RE 时，可以记住三件事：对象文件留下重定位、目标内核暴露类型信息、加载器据此做适配；这三环缺一不可。\n\n来源：[Linux 内核文档：BPF LLVM Relocations](https:\u002F\u002Fdocs.kernel.org\u002Fbpf\u002Fllvm_reloc.html)","\u002Fuploads\u002F2026-10-17\u002Fb0b1f080-c239-4099-9075-93019c192721.jpg",[],[],"Foundit","https:\u002F\u002Ffoundit.cn","foundit-ai-editorial",{"id":18,"name":19,"slug":20,"description":21},"6179d3b6-dc34-4483-9ded-3cd9f1b37a47","科普","abbreviation","介绍各领域新兴概念",[23,27,31],{"id":24,"name":25,"slug":26},"7c76bfc2-f80f-4ee0-a95d-27bd8708b434","技术","slug",{"id":28,"name":29,"slug":30},"144abe77-0dc6-4f66-a176-20bddb1c0bfa","编程","coding",{"id":32,"name":33,"slug":34},"a202d639-99a6-488a-a712-4d4c6ffd7e15","开发","dev","Linux Kernel Documentation","https:\u002F\u002Fdocs.kernel.org\u002Fbpf\u002Fllvm_reloc.html","published",null,false,50,0,"2026-10-17T00:00:00.000Z","2026-10-17T03:08:31.511Z",[45,53,61],{"id":46,"type":6,"title":47,"slug":48,"summary":49,"coverUrl":50,"authorName":14,"sno":51,"publishedAt":42,"createdAt":52},"4ce57934-2b23-41a1-800e-bb2d8ab36684","Wasm Component Model：不同语言写的模块怎样用同一套接口协作？","wasm-component-model-wit-interfaces","WebAssembly Component Model 用有类型的接口描述组件如何交换数据与调用功能，WIT 则帮助表达这些接口。本文用模块化电器说明跨语言组合的意义，也指出它不代表程序脱离运行时就能在任何环境原样运行。","\u002Fuploads\u002F2026-10-17\u002F0eb1c88d-dc1f-486d-8194-54f72dd215ec.jpg",45,"2026-10-17T03:08:52.474Z",{"id":54,"type":6,"title":55,"slug":56,"summary":57,"coverUrl":58,"authorName":14,"sno":51,"publishedAt":59,"createdAt":60},"07fe8e6e-82b0-46cc-9015-c6d027564430","pidfd：进程号会被重用，怎样才能稳定指向一个进程？","linux-pidfd-stable-process-reference","Linux pidfd 用文件描述符稳定引用一个进程，避免退出后的 PID 被重用而误操作新进程。本文介绍它的等待、信号用途和版本边界。","\u002Fuploads\u002F2026-10-06\u002F699e59f8-693f-47cb-87b1-c51764d1a679.jpg","2026-10-06T00:00:00.000Z","2026-10-06T07:51:27.054Z",{"id":62,"type":6,"title":63,"slug":64,"summary":65,"coverUrl":66,"authorName":14,"sno":51,"publishedAt":67,"createdAt":68},"15988123-6303-4ab1-ba01-dcc41f36329f","Futex：Linux 的锁为什么大多数时候根本不需要进内核？","futex-fast-userspace-locking","Futex 把无竞争时的锁操作留在用户态，只有真正需要睡眠和唤醒时才进入内核，是 Linux 高性能锁的关键低层构件。","\u002Fuploads\u002F2026-09-26\u002F90e98cc8-e57b-4dea-afc7-2afe7550d483.jpg","2026-09-27T00:00:00.000Z","2026-09-26T16:25:54.119Z"]