基于bcc的Python eBPF(扩展伯克利包过滤器)包装器
项目描述
PyEBPF
一个基于bcc的Python eBPF(扩展伯克利包过滤器)包装器。
注意:使用此库需要安装BCC,请参阅此指南。
此小型库有两个主要目的
- 它允许您在不编写本地代码的情况下附加BPF内核探测
- 它允许您在Python中编写BPF例程回调 [1]
如果您需要该功能,您仍然可以像使用bcc的BPF库一样编写、编译和使用本地例程。
[1] 请参阅下面的 '此库是如何工作的?'
什么是eBPF
扩展伯克利包过滤器是BPF过滤器(传统上用于包过滤)的超集,它允许您使用专用eBPF指令集编写小的内核例程。
要使用eBPF,需要编译一个例程,调用bpf(2)系统调用,并附加一个内核探测。
bpf(2)将确保取您的编译后的例程,静态分析并JIT它,然后将其复制到内核空间以供以后使用。
您将一个探测附加到内核跟踪事件(例如系统调用调用),一旦您的探测附加,您的eBPF例程将被适当地调用。
通过eBPF映射(在FD之上操作,允许在这些两端之间通信)在eBPF例程之间或eBPF例程与用户空间之间共享数据是可能的。
什么是IOVisor/BCC
BCC(BPF编译器集合)是一个工具包,可以帮助您以用户友好的方式生成和使用BPF例程。
它通过C宏抽象了一些eBPF功能(例如BPF共享数据结构),让您专注于例程的逻辑和收集适当的指标。
代码生成由LLVM管理,因此您需要安装适当的版本。
更多关于项目的信息,请访问此处。
这个库是如何工作的?
给定一个需要附加内核探针的事件,这个库将(按顺序)
-
尝试隐式猜测事件传递给您的例程的任何额外参数。这是通过尽力阅读/sys/kernel/debug/tracing/events/syscalls/sys_enter_/format文件来完成的。该文件包含事件跟踪可能包含的参数的文本描述。
-
然后它将生成一个精心设计的本地数据结构,其中将包含相关上下文,包括
- 当前时间(以纳秒为单位)(通过bpf_ktime_get_ns)
- PID和TID(通过bpf_get_current_pid_tgid)
- GID和UID(通过bpf_get_current_uid_gid)
- 进程名称(通过bpf_get_current_comm)
- 任何隐式猜测的事件跟踪参数,例如对于bind系统调用,数据结构将还包含:套接字FD、套接字地址和地址长度
-
它将创建一个eBPF共享数据结构(使用BPF_PERF_OUTPUT宏),用作与用户模式例程的通信网关
-
将启动一个专用的轮询守护进程线程,并且对于共享结构上的每个输出,您的Python回调将被调用,并通过ctypes类传递表示本地数据结构
因此,对于任何内核探针附加的事件,将调用一个内部BPF例程,然后它将所有相关成员通过构造的数据结构复制回用户模式,通过BPF结构。然后,一个内部Python线程将轮询该结构,并调用已注册的Python回调。
有效地使用此包装器
首先,通过以下命令安装库
$> pip install pyebpf
然后,导入EBPFWrapper对象,实例化它,并将函数附加到事件上。
# trace_fields.py bcc example, using pyebpf
b = EBPFWrapper()
print 'PID MESSAGE'
def hello(data, **kwargs):
print '{pid} Hello, World!'.format(pid=data.process_id)
b.attach_kprobe(event=b.get_syscall_fnname('clone'), fn=hello)
while True:
try:
time.sleep(1)
except KeyboardInterrupt:
print 'Bye !'
break
b = EBPFWrapper()
print 'COMM PID SOCKETFD'
def on_bind(data, **kwargs):
print '{comm} {pid} {fd}'.format(comm=data.process_name, pid=data.process_id, fd=data.fd, addr=data.umyaddr)
b.attach_kprobe(event=b.get_syscall_fnname('bind'), fn=on_bind)
# Will print 'python <pid> <fd>'
s = socket()
s.bind(('0.0.0.0', 31337))
while True:
try:
time.sleep(1)
except KeyboardInterrupt:
print 'Bye !'
break
# Supplying a native route
from pyebpf.ebpf_wrapper import EBPFWrapper
prog = '''
int hello(struct pt_regs* ctx) {
bpf_trace_printk("Hello from eBPF routine!\\n");
return 0;
}
'''
b = EBPFWrapper(text=prog)
b.attach_kprobe(event='sys_open', fn_name='hello')
while True:
try:
print b.trace_fields()
except KeyboardInterrupt:
print 'Bye !'
break
EBPF相关资源
以下是我在编写此库时找到的一些有用的eBPF相关资源
项目详情
下载文件
下载适用于您平台的应用程序。如果您不确定要选择哪个,请了解更多关于安装包的信息。
源分布
构建分布
pyebpf-1.0.4.tar.gz的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | f563cc0e1759b165d89aab03db01252cc2b4c40805f6bd32485fdcb710584bb0 |
|
MD5 | e624f38fd73e2596270910ab33ca3184 |
|
BLAKE2b-256 | 097aec23a0851d39adb1997f38be10857dabca2affba3cb4664d0b66efbc4cd0 |