最近发布的Linux内核带了一个针对内核的能力强大的Linux监控框架。它起源于历史上人们所说的的BPF。
BPF是什么?BPF(BerkeleyPacketFilter)是一个非常高效的网络包过滤机制,它的目标是避免不必要的用户空间申请。它直接在内核空间处理网络数据包。BPF支持的最常见的应用就是tcpdump工具中使用的过滤器表达式。在tcpdump中,表达式被编译转换为BPF的字节码。内核加载这些字节码并且用在原始网络包流中,以此来高效的把符合过滤条件的数据包发送到用户空间。
eBPF又是什么?eBPF是对Linux观测系统BPF的扩展和加强版本。可以把它看作是BPF的同类。有了eBPF就可以自定义沙盒中的字节码,这个沙盒是eBPF在内核中提供的,可以在内核中安全的执行几乎所有内核符号表抛出的函数,而不用担心搞坏内核。实际上,eBPF也是加强了在和用户空间交互的安全性。在内核中的检测器会拒绝加载引用了无效指针的字节码或者是已达到最大栈大小限制。循环也是不允许的(除非在编译时就知道是有常数上线的循环),字节码只能够调用一小部分指定的eBPF帮助函数。eBPF程序保证能及时终止,避免耗尽系统资源,而这种情况出现在内核模块执行中,内核模块会造成内核的不稳定和可怕的内核崩溃。相反的,你可能会发现和内核模块提供的自由度来比,eBPF有太多限制了,但是综合考虑下来还是更倾向于eBPF,而不是面向模块的代码,主要是基于授权后的eBPF不会对内核造成损害。然而这还不是它唯一的优势。
为什么用eBPF来做Linux监控?作为Linux内核核心的一部分,eBPF不依赖于任何第三方模块或者扩展依赖。它包含了稳定的ABI(应用程序二进制接口),可以让在老内核上编译的程序在新内核上运行。由eBPF带来的性能开销通常可以忽略不计,这让它非常适合做应用监控和跟踪很重的系统执行。窗口用户没有eBPF,但是他们可以使用窗口事件跟踪。
eBPF是非常灵活而且可以跟踪几乎所有的主要内核子系统:涵盖了CPU调度,内存管理,网络,系统调用,块设备请求等等。而且仍然在扩展中。
可以在终端里运行下面的命令看到所有能用eBPF跟踪的内核符号列表:
$cat/proc/kallsyms
可以跟踪的符号
Theabove