linux编译支持ebpf,Linux内核功能eBPF入门学习(一):BPF、eBPF、BCC等基本概念

Linux内核观测技术BP

目录

说明

eBPF是kernel 3.15中引入的全新设计,将原先的BPF发展成一个指令集更复杂、应用范围更广的“内核虚拟机”。

eBPF支持在用户态将C语言编写的一小段“内核代码”注入到内核中运行,注入时要先用llvm编译得到使用BPF指令集的elf文件,然后从elf文件中解析出可以注入内核的部分,最后用bpf_load_program方法完成注入。 用户态程序和注入到内核中的程序通过共用一个位于内核中map实现通信。为了防止注入的代码导致内核崩溃,eBPF会对注入的代码进行严格检查,拒绝不合格的代码的注入。

BCC是一个python库,实现了map创建、代码编译、解析、注入等操作,使开发人员只需聚焦于用C语言开发要注入的内核代码。 文章eBPF简史从eBPF的前身BPF讲起,将eBPF的来龙去脉介绍的很明白,是难得的好文章,建议直接过去阅读,这里就不摘抄了。 BPF: the universal in-kernel virtual machine介绍了BPF从网络子系统中的报文复制功能到内核通用虚拟机eBPF的演变过程。

BPF

BPF是很早就有的内核特性,在内核中将报文“镜像”了一份,并用BPF指令检查镜像出来的报文、决定报文的去留,即在1)抛弃报文和2)将其复制到用户空间之间抉择。

具体实现就不去了解了,BPF好歹设计了一套指令集,虽然比较简单,但没有扎实的编译原理基础,估计一时半会儿也看不懂,这里只收集一下相关文档:

另外学到了一个新知识,tcpdump使用的libpcap是基于BPF的,在使用tcpdump或者libpcap时传入的“host 192.168.1.1”、“tcp and port 80”等是过滤表达式。

过滤表达式会被编译成BPF指令,在tcpdump命令后面加上-d参数可以看到:

$ tcpdump -d -i eth0 tcp and port 80

(000) ldh [12]

(001) jeq #0x86dd jt 2 jf 8

(002) ldb [20]

(003) jeq #0x6 jt 4 jf 19

(004) ldh [54]

(005) jeq #0x50 jt 18 jf 6

(006) ldh [56]

(007) jeq #0x50 jt 18 jf 19

(008) jeq #0x800 jt 9 jf 19

(009) ldb [23]

(010) jeq #0x6 jt 11 jf 19

(011) ldh [20]

(012) jset #0x1fff jt 19 jf 13

(013) ldxb 4*([14]&0xf)

(014) ldh [x + 14]

(015) jeq #0x50 jt 18 jf 16

(016) ldh [x + 16]

(017) jeq #0x50 jt 18 jf 19

(018) ret #65535

(019) ret #0

这些BPF指令是在内核中被BPF解释执行的。

eBPF带来的新变化

原先的BPF依然支持,用cBPF指代。eBPF全新设计了更丰富的指令集、增加了寄存器,性能大幅提高:

The original patch that added support for eBPF in the 3.15 kernel showed that eBPF was up to four times faster on x86-64 than the old classic BPF (cBPF) implementation for some network filter microbenchmarks, and most were 1.5 times faster.

增加了名为bpf的系统调用,为用户态程序提供与内核中的eBPF进行交互的途径:

int bpf(int cmd, union bpf_attr *attr, unsigned int size);

cmd是eBPF支持的cmd,分为三类: 操作注入的代码、操作用于通信的map、前两个操作的混合。

通过eBPF可以做更多的事情,不再仅仅是进行报文复制和过滤,网络方面可以切入到更深的层次,在更“靠前”的阶段进行干预,例如XDP借助eBPF在报文刚收到的时候就进行干预,使用XDP(eXpress Data Path)防御DDoS攻击。

还可以:

限制进程可以使用的系统调用,seccomp;

输出内核中的数据,进行内核调试、性能分析、调用跟踪;

eBPF使用

eBPF是kernel 3.15开始支持的,在kernel 3.17源码中获得了一个单独的bpf目录,建议直接使用3.17以及以上版本的内核。下面这四篇文章可以帮你搭建对eBPF的认知框架:

升级内核

eBPF代码示例

samples/bpf,暂时没有找到相关资料,目前以学习bcc的使用为主,2019-02-25 18:11:40

eBPF代码编译装载

同上一节。

使用BCC简化eBPF应用开发过程

BCC首先提供了一个名为bcc的python库,简化了eBPF应用的开发过程,然后它收集大量的eBPF应用,主要是性能分析相关的。 可以直接使用bcc已经收集的命令调查问题(bcc Tutorial),也可以用bcc提供的python库自己开发eBPF应用(bcc Python Developer Tutorial)。

Kernel版本需要是4.1以上(2019-02-25 18:08:15),并且要安装kernel-devel,如果没有安装kernel-devel,eBPF应用会汇编译失败(bcc收集的命令运行时也会出现下面错误):

# execsnoop

chdir(/lib/modules/4.20.12-1.el7.elrepo.x86_64/build): No such file or directory

Traceback (most recent call last):

File "/usr/share/bcc/tools/execsnoop", line 166, in

b = BPF(text=bpf_text)

File "/usr/lib/python2.7/site-packages/bcc/__init__.py", line 318, in __init__

raise Exception("Failed to compile BPF text")

Exception: Failed to compile BPF text

BCC安装

直接用yum安装:

yum install bcc-tools

用rpm -ql可以看到所有bcc文件,tools/目录中是bcc提供的命令,可以用man查看对应的手册,比如man bcc-argdist:

$ rpm -ql bcc-tools

/usr/share/bcc

/usr/share/bcc/introspection

/usr/share/bcc/introspection/bps

/usr/share/bcc/tools

/usr/share/bcc/tools/argdist

/usr/share/bcc/tools/bashreadline

/usr/share/bcc/tools/biolatency

...

/usr/share/bcc/tools/doc

/usr/share/bcc/tools/doc/argdist_example.txt

/usr/share/bcc/tools/doc/bashreadline_example.txt

/usr/share/bcc/tools/doc/biolatency_example.txt

/usr/share/bcc/tools/doc/biosnoop_example.txt

...

/usr/share/man/man8/bcc-argdist.8.gz

/usr/share/man/man8/bcc-bashreadline.8.gz

/usr/share/man/man8/bcc-biolatency.8.gz

/usr/share/man/man8/bcc-biosnoop.8.gz

/usr/share/man/man8/bcc-biotop.8.gz

BCC收集的eBPF应用

BCC的命令较多,单开一篇笔记,这篇到此为止。

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值