<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh">
	<id>https://arolstar52-zhtest.hf.space/index.php?action=history&amp;feed=atom&amp;title=BPF</id>
	<title>BPF - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://arolstar52-zhtest.hf.space/index.php?action=history&amp;feed=atom&amp;title=BPF"/>
	<link rel="alternate" type="text/html" href="https://arolstar52-zhtest.hf.space/index.php?title=BPF&amp;action=history"/>
	<updated>2026-07-13T14:04:49Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://arolstar52-zhtest.hf.space/index.php?title=BPF&amp;diff=580990&amp;oldid=prev</id>
		<title>2025年8月27日 (三) 02:18 imported&gt;KSroido</title>
		<link rel="alternate" type="text/html" href="https://arolstar52-zhtest.hf.space/index.php?title=BPF&amp;diff=580990&amp;oldid=prev"/>
		<updated>2025-08-27T02:18:42Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Expert needed|subject=计算机科学|time=2011-12-08}}&lt;br /&gt;
{{Expand language|en|time=2023-10-27T06:27:43+00:00}}&lt;br /&gt;
{{NoteTA|G1=IT}}&lt;br /&gt;
{{不是|eBPF}}&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;伯克利包过滤器&amp;#039;&amp;#039;&amp;#039;（{{langx|en|Berkeley Packet Filter}}，缩写 BPF），是[[类Unix]]系统上[[数据链路层]]的一种原始接口，提供原始链路层[[封包]]的收发。除此之外，如果网卡驱动支持[[混杂模式]]，那么它可以让网卡处于此种模式，这样可以收到[[网络]]上的所有包，不管他们的目的地是不是所在[[主机]]。&lt;br /&gt;
&lt;br /&gt;
另外，BPF支持过滤数据包——用户态的进程可以提供一个过滤程序来声明它想收到哪些数据包。通过这种过滤可以避免从[[操作系统]][[内核]]向用户态复制其他对用户态程序无用的数据包，从而极大地提高性能。&lt;br /&gt;
&lt;br /&gt;
BPF有时也只表示过滤机制，而不是整个接口。一些系统，比如[[Linux]]和Tru64 Unix，提供了数据链路层的原始接口，而不是BPF的接口，但使用了BPF的过滤机制。&lt;br /&gt;
&lt;br /&gt;
BSD 内核实现例程如 &amp;lt;code&amp;gt;bpf_mtap()&amp;lt;/code&amp;gt;和 &amp;lt;code&amp;gt;bpf_tap()&amp;lt;/code&amp;gt;，以&amp;lt;code&amp;gt;BPF_MTAP()&amp;lt;/code&amp;gt;和 &amp;lt;code&amp;gt;BPF_TAP()&amp;lt;/code&amp;gt;等[[宏定义]]的形式进行包裹由网卡驱动(以及伪驱动pseudo-drivers) 向BPF机制发送进出的封包。&lt;br /&gt;
&lt;br /&gt;
== 历史 ==&lt;br /&gt;
原始的论文由Steven McCanne 和 Van Jacobson于1992年在[[劳伦斯伯克利国家实验室]]工作时编写，于1993年在San Diego举办的USENIX冬季会议上正式发表。&lt;br /&gt;
&lt;br /&gt;
== 背景 ==&lt;br /&gt;
许多版本的Unix操作系统提供了用于捕获数据包的设施，使得监控当前网络情况成为了可能。但是，因为网络监控程序运行在用户态，数据包必须被拷贝来通过内核与用户态之间的边界。可以通过使用一种被称为“数据包过滤器”的内核代理来减少拷贝的数量，它会尽量早地丢弃不想要的数据包。早先的数据包过滤器被实现为基于栈的虚拟机，在RISC CPU上性能不佳。BPF使用了一种新的基于寄存器(Register)的虚拟机，在性能上有显著提升。&amp;lt;ref&amp;gt;{{Cite journal|title=The BSD Packet Filter: A New Architecture for User-level Packet Capture|url=http://dl.acm.org/citation.cfm?id=1267303.1267305|last=McCanne|first=Steven|last2=Jacobson|first2=Van|date=1993|journal=Proceedings of the USENIX Winter 1993 Conference Proceedings on USENIX Winter 1993 Conference Proceedings|publisher=USENIX Association|series=USENIX&amp;#039;93|location=Berkeley, CA, USA|pages=2–2}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 过滤 ==&lt;br /&gt;
BPF的过滤功能是以对于BPF[[虚拟机]][[机器语言]]的一种[[解释器]]的形式实现的，使用这种语言编写的程序可以抓取数据包，对数据包中的数据采取算术操作，并将结果与常量或数据包中的数据或结果中的测试位比较，根据比较的结果决定接受还是拒绝封包。&lt;br /&gt;
&lt;br /&gt;
传统的Unix BPF实现能够被用于用户态，尽管它是为内核态编写。这是通过编译时的条件预处理完成的。&lt;br /&gt;
&lt;br /&gt;
== 优化 ==&lt;br /&gt;
一些项目使用了不同以往的BPF指令集或者执行方法。&lt;br /&gt;
&lt;br /&gt;
包括[[FreeBSD]]和WinPcap在内的一些平台，使用[[JIT|即时编译]]（JIT）编译器来把BPF指令转换为原始字节码，以进一步提高性能。Linux有一个BPF JIT编译器，但被默认禁用。&lt;br /&gt;
&lt;br /&gt;
此虚拟机语言的内核态解释器则被用于其他操作系统的原始数据链路机制，例如[[Tru64 Unix]]系统，以及[[Linux]]内核中的[[套接字]]过滤器，和[[WinPcap]]数据包抓取机制。&lt;br /&gt;
&lt;br /&gt;
用户态解释器由实现了[[pcap]] [[API]]的libpcap/WinPcap提供，因此，在对此过滤机制没有内核态支持的系统上抓取数据包时，数据包可以在内核态过滤，使用pcap API的代码可以工作于此两种模式；在使用用户态过滤的系统上，所有数据包由内核态复制到用户态，包括将被过滤出去的封包。这种解释器也可以用于包含由pcap抓取的封包的文件。&lt;br /&gt;
&lt;br /&gt;
2007年，{{link-en|Robert Watson|Robert Watson (computer scientist)}}与Christian Peron为[[FreeBSD]]操作系统中BPF的实现加入了zero-copy buffer extension，使得驱动程序中断处理器中的内核封包抓取能直接向用户内存写，以避免BPF设备收到的所有封包数据的两次复制需要，一份副本存在于用户进程的接收路径中，这保证了不同BPF设备调用者的独立性，同时使得只把封包头部放入BPF缓冲区，而不是复制整个封包数据。&lt;br /&gt;
&lt;br /&gt;
Will Drewry为seccomp（安全计算）系统调用策略添加了BPF过滤器，这也是BPF第一次在网络领域之外的使用。&amp;lt;ref name=&amp;quot;:0&amp;quot;&amp;gt;{{Cite book|chapter=Chapter 2. Technology Background|url=https://book.douban.com/subject/34467459/|publisher=Addison Wesley|date=2019-11-04|isbn=9780136554820|first=Brendan|last=Gregg|title=BPF Performance Tools|year=|location=|pages=|access-date=2019-10-04|archive-date=2019-10-04|archive-url=https://web.archive.org/web/20191004004134/https://book.douban.com/subject/34467459/|dead-url=no}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== eBPF ==&lt;br /&gt;
从3.18版本开始，Linux 内核提供了一种扩展的BPF虚拟机，被称为“extended BPF”，简称为eBPF。它能够被用于非网络相关的功能，比如附在不同的tracepoints上，从而获取当前内核运行的许多信息。&amp;lt;ref&amp;gt;{{Cite web|title=Extending extended BPF [LWN.net]|url=https://lwn.net/Articles/603983/|accessdate=2019-10-02|work=lwn.net|archive-date=2019-04-24|archive-url=https://web.archive.org/web/20190424023546/https://lwn.net/Articles/603983/|dead-url=no}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
传统的BPF，现在被称为cBPF（classical BPF）。&lt;br /&gt;
&lt;br /&gt;
eBPF由Alexei Starovoitov在PluMgrid工作时设计，这家公司专注于研究新的方法来设计[[軟體定義網路|软件定义网络]]解决方案。在它只是一个提议时，Daniel Borkmann——Red Hat公司的内核工程师，帮助修改使得它能够进入内核代码并完全替代已有的BPF实现。这是二十年来BPF首次主要的更新，使得BPF成为了一个通用的虚拟机。&amp;lt;ref name=&amp;quot;:0&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eBPF被Linux内核合并的事件线如下&amp;lt;ref name=&amp;quot;:0&amp;quot; /&amp;gt;：&lt;br /&gt;
&lt;br /&gt;
* 2014年3月。eBPF补丁被合并到Linux内核。&lt;br /&gt;
* 2014年6月。JIT组件被合并到内核3.15版本。&lt;br /&gt;
* 2014年12月。bpf系统调用被合并到内核3.18版本。&lt;br /&gt;
* 在后来的Linux 4.x系列版本中又添加了对于kprobes、uprobes、tracepoints以及perf_events的支持。&lt;br /&gt;
&lt;br /&gt;
因为eBPF虚拟机使用的是类似于汇编语言的指令，对于程序编写来说直接使用难度非常大。和将C语言生成汇编语言类似，现在的编译器正在逐步完善从更高级的语言生成BPF虚拟机使用的指令。LLVM在3.7版本开始支持BPF作为后端输出。&amp;lt;ref&amp;gt;{{Cite web|title=BPF Backend Merged Into LLVM To Make Use Of New Kernel Functionality - Phoronix|url=https://www.phoronix.com/scan.php?page=news_item&amp;amp;px=LLVM-BPF-VM-Backend-Lands|accessdate=2019-10-04|work=www.phoronix.com|archive-date=2020-01-24|archive-url=https://web.archive.org/web/20200124153457/https://www.phoronix.com/scan.php?page=news_item&amp;amp;px=LLVM-BPF-VM-Backend-Lands|dead-url=no}}&amp;lt;/ref&amp;gt;GCC 10也将会支持BPF作为后端。&amp;lt;ref&amp;gt;{{Cite web|title=Oracle Is Aiming To Contribute An eBPF Backend To The GCC 10 Compiler - Phoronix|url=https://www.phoronix.com/scan.php?page=news_item&amp;amp;px=GCC-10-eBPF-Backend-Plans|accessdate=2019-10-04|work=www.phoronix.com|archive-date=2019-06-22|archive-url=https://web.archive.org/web/20190622051918/https://www.phoronix.com/scan.php?page=news_item&amp;amp;px=GCC-10-eBPF-Backend-Plans|dead-url=no}}&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;{{Cite web|title=[PATCH 0/8] eBPF support for GCC [LWN.net]|url=https://lwn.net/ml/gcc-patches/20190814213651.20286-1-jose.marchesi@oracle.com/|accessdate=2019-10-04|work=lwn.net}}&amp;lt;/ref&amp;gt;BCC是IOVisor项目下的编译器工具集，用于创建内核跟踪（tracing）工具。&amp;lt;ref&amp;gt;{{Cite web|title=BCC|url=https://www.iovisor.org/technology/bcc|accessdate=2019-10-04|work=IO Visor Project|language=en-US|archive-date=2020-06-10|archive-url=https://web.archive.org/web/20200610105334/https://www.iovisor.org/technology/bcc|dead-url=no}}&amp;lt;/ref&amp;gt;bpftrace是为eBPF设计的高级跟踪语言，在Linux内核（4.x）中提供。&amp;lt;ref&amp;gt;{{Citation|title=bfptrace(Github)|url=https://github.com/iovisor/bpftrace|publisher=IO Visor Project|date=2019-10-04|accessdate=2019-10-05|archive-date=2019-10-02|archive-url=https://web.archive.org/web/20191002075605/https://github.com/iovisor/bpftrace|dead-url=no}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eBPF现在被应用于网络、跟踪、内核优化、硬件建模等领域。&amp;lt;ref&amp;gt;{{Cite journal|title=BPF - in-kernel virtual machine|url=https://www.slideshare.net/AlexeiStarovoitov/bpf-inkernel-virtual-machine?qid=d4cfb32d-67c3-4de4-b359-c50ceb605a5c&amp;amp;v=&amp;amp;b=&amp;amp;from_search=5|last=Alexei Starovoitov|date=2015-02-23}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 安全 ==&lt;br /&gt;
[[幽灵漏洞|Spectre]]攻击可以利用Linux内核的eBPF JIT编译器来从其它内核进程提取信息。&amp;lt;ref&amp;gt;{{Cite web|title=Project Zero: Reading privileged memory with a side-channel|url=https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.html|accessdate=2019-10-03|date=2018-01-03|last=Ben|work=Project Zero|archive-date=2019-10-01|archive-url=https://web.archive.org/web/20191001221349/https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.html|dead-url=yes}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 参考文献 ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
== 外部链接 ==&lt;br /&gt;
* [http://www.tcpdump.org/papers/bpf-usenix93.pdf The BSD Packet Filter: A New Architecture for User-level Packet Capture]{{Wayback|url=http://www.tcpdump.org/papers/bpf-usenix93.pdf |date=20090419143212 }} (PDF)&lt;br /&gt;
* [http://www.watson.org/~robert/freebsd/2007asiabsdcon/20070309-devsummit-zerocopybpf.pdf FreeBSD开发者大会上讲述BPF中Zero-copy的材料]{{Wayback|url=http://www.watson.org/~robert/freebsd/2007asiabsdcon/20070309-devsummit-zerocopybpf.pdf |date=20080516213834 }} (PDF)&lt;br /&gt;
* [http://www.FreeBSD.org/cgi/man.cgi?query=bpf&amp;amp;apropos=0&amp;amp;sektion=0&amp;amp;manpath=FreeBSD+8-current&amp;amp;format=html FreeBSD 8.x BPF(4)手册,包含 zero-copy BPF缓冲区的描述]{{Wayback|url=http://www.freebsd.org/cgi/man.cgi?query=bpf&amp;amp;apropos=0&amp;amp;sektion=0&amp;amp;manpath=FreeBSD+8-current&amp;amp;format=html |date=20200516005207 }}&lt;br /&gt;
*[https://qmonnet.github.io/whirl-offload/2016/09/01/dive-into-bpf/ BPF阅读清单]{{Wayback|url=https://qmonnet.github.io/whirl-offload/2016/09/01/dive-into-bpf/ |date=20191002075614 }}&lt;br /&gt;
&lt;br /&gt;
[[Category:网络软件]]&lt;br /&gt;
[[Category:封包]]&lt;/div&gt;</summary>
		<author><name>imported&gt;KSroido</name></author>
	</entry>
</feed>