侵权投诉

eBPF是什么以及eBPF能干什么

Linux阅码场 2021-07-05 15:17 次阅读

一、eBPF是什么

eBPF是extended BPF的缩写,而BPF是Berkeley Packet Filter的缩写。对linux网络比较熟悉的伙伴对BPF应该比较了解,它通过特定的语法规则使用基于寄存器的虚拟机来描述包过滤的行为。比较常用的功能是通过过滤来统计流量,tcpdump工具就是基于BPF实现的。而eBPF对它进行了扩展来实现更多的功能。

主要区别如下:

1)允许使用C 语言编写代码片段,并通过LLVM编译成eBPF 字节码;2)cBPF 只实现了SOCKET_FILTER,而eBPF还有KPROBE 、PERF等。3)BPF使用socket 实现了用户态与内核交互,eBPF 则定义了一个专用于eBPF 的新的系统调用,用于装载BPF 代码段、创建和读取BPF map,更加通用。4)BPF map 机制,用于在内核中以key-value 的方式临时存储BPF 代码产生的数据。

对于eBPF可以简单的理解成kernel实现了一个虚拟机机制,将类C代码编译成字节码(后文有详细解释),挂在到内核的钩子上,当钩子被触发时,kernel在虚拟机的“沙盒”中运行字节码,这样既能方便的实现很多功能,也能通过沙箱保证内核的安全性。

二、eBPF能干什么

如果说BPF专注于流量监控,那么eBPF主要专注的是性能领域,通过各种钩子,能在用户空间得到系统各种性能指标。可以大到监控系统整体的统计指标,也可以小到一个系统函数的运行时间。

这里需要提一下开源项目 BPF Compiler Collection (BCC),这是一个很方便的基于eBPF的系统监视工具,下面这张BCC的说明图就能很好的说明我们使用eBPF能够做到的事。BCC在android系统上也可以运行,但是要对系统进行一定程度的修改,后续可能会写单独的文章进行讲解。对于内核开发者我还比较关注怎么自己来实现监控的功能,下文也将做简单的讲解。

从上图,我么可以看到,eBPF几乎能监控系统的所有方面:

1)应用及虚拟机的各种指标2)系统库性能监控3)kernel系统调用性能4)文件系统性能5)网络调用性能6)CPU调度器性能7)内存管理性能8)中断性能

三、eBPF框架

在开始说明之前先解释下eBPF上的名词,来帮忙更好的理解。

1)eBPF bytecode:将C语言写的钩子代码,通过clang编译成二进制字节码,通过程序加载到内核中,钩子触发后在kernel “虚拟机”中运行。2)JIT: Just-in-time compilation,将字节码编译成本地机器码来提升运行速度,和Java中的概念类似。

3)Maps:钩子代码可以将一些统计类信息保存在键值对的map中,来与用户空间程序进行通信,传递数据。

关于eBPF机制详细的讲解网上有很多,这里就不展开了,这里先上一张图,这里包括了使用或者编写ebpf涉及到的所有东西,下面会对这个图进行详细的讲解。

1)foo_kern.c 钩子实现代码,主要负责:

声明使用的Map节点

声明钩子挂载点及处理函数

2)通过LLVM/clang编译成字节码

编译命令:clang --target=bpf

android平台有集成eBPF的编译,后文会提到

3)foo_user.c 用户空间处理函数,主要负责:

将foo_kern.c 编译成的字节码加载到kenel中

读取Map中的信息并处理输出给用户

4)kernel当收到eBPF的加载请求时,会先对字节码进行验证,并通过JIT编译为机器码,当钩子事件来临后,调用钩子函数 kernel会对加载的字节码进行验证,来保证系统的安全性,主要验证规则如下:

a. 检查是否声明了GNU GPL,检查kernel的版本是否支持

b. 函数调用规则:

允许bpf函数之间的相互调用

只允许调用kernel允许的BPF helper函数,具体可以参考linux/bpf.h文件

上述以外的函数及动态链接都是不允许的。

c. 流程处理规则:

不允许使用loop循环以防止进入死循环卡死kernel

不允许有不可到达的分支代码

d. 堆栈大小被限制在MAX_BPF_STACK范围内。

e. 编译的字节码大小被限制在BPF_COMPLEXITY_LIMIT_INSNS范围内。

5)钩子挂载点,主要包括:

另外在kernel的源代码中samples/bpf目录下有大量的示例,感兴趣的可以阅读下。

四、eBPF在Android平台的使用

经过上面枯燥的讲解,大家应该对eBPF有了基础的认识,下面我们就来通过android平台上的一个监控性能的小例子来实操下。

这个小例子的需求是统计系统中每个应用在一段时间内系统调用的次数。

1. android系统对eBPF的编译支持

目前android编译系统已经对eBPF进行了集成,通过android.bp就能很方便的在android源代码中编译eBPF的字节码。

android.bp示例:

相关的编译代码在soong的bpf.go,虽然google关于soong的文档很少,但是至少代码是比较清晰的。

这里的$ccCmd一般是clang, 所以它的编译命令主要是clang --target=bpf。和普通的bpf编译没有区别。

2. eBPF钩子代码实现

解决了编译问题,下一步我们开始实现钩子代码,我们准备使用tracepoint钩子,首先要找到我们需要的tracepoint函数sys_enter和sys_exit。

函数定义在include/trace/events/syscalls.h文件中

1)sys_enter的trace参数是id 和长度为6的数组。2)sys_exit的trace参数是两个长整形数 id 和ret。

找到了钩子后,下一步就可以编写钩子处理代码了:

1)定义map保存系统调用统计信息,在DEFINE_BPF_MAP声明map的同时,也会生成删,改,查的宏函数,例如本例中会生成如下函数

bpf_pid_syscall_map_lookup_elem

bpf_pid_syscall_map_update_elem

bpf_pid_syscall_map_delete_elem

2)定义回调函数参数类型,需要参考前面的tracepoint的定义。3)指定监听的tracepoint事件。4)使用bpf_trace_printk函数打印debug信息,会直接打印信息到ftrace中。5)在map中查找指定key。6)更新指定的key的值。

3. 加载钩子代码

我们只需要把我们编译出来的*.o文件push到手机的system/etc/bpf目录下,重启手机,系统会自动加载我们的钩子文件,加载成功后会在 /sys/fs/bpf目录下显示我们定义的map及prog文件。

系统加载代码在system/bpf/bpfloader中,代码很简单。

主要有如下操作:

1)在early-init阶段向下面两个节点写1

– /proc/sys/net/core/bpf_jit_enable

使能eBPF JIT,当内核设定BPF_JIT_ALWAYS_ON的时候,默认为1

– /proc/sys/net/core/bpf_jit_kallsyms

使特权用户可以通过kallsyms节点读取kernel的symbols

2)启动bpfloader service

– 读取system/etc/bpf目录下的*.o文件,调用libbpf_android.so中的loadProg函数加载进内核。

– 生成相应的/sys/fs/bpf/节点。

– 设置属性bpf.progs_loaded为1

sys节点分为map节点和prog节点两种, 分别为map_《filename》_《mapname》, prog_《filename》_《mapname》

下面是Android Q版本上的节点信息。

可以使用下面的命令调试动态加载

4. 用户空间程序实现

下面我们需要编写用户空间的显示程序,本质上就是在用户态通过系统调用把BPF map给读出来。

1)eBPF统计只有在调用bpf_attach_tracepoint只有才会起作用。bpf_attach_tracepoint是bcc里面的函数,android将bcc的一部分内容打包成了libbpf,放到了系统库里面。2)取得map的fd, bpf_obj_get会直接调用bpf的系统调用。3)将fd包装成BpfMap,android在BpfMap.h中定义了很多方便的函数。4)遍历map回调函数。返回值必须是android::ok(在android的新版本中已经进行修改)。

5. 运行结果查看

直接在目录下执行mm,将编译出来的bpf.o push到/system/etc/bpf目录下,将统计程序push到/system/bin目录下,重启,看下结果。

前面的是pid, 后面的是系统调用次数。

至此,如何在android平台使用eBPF实现统计系统中每个pid在一段时间内系统调用的次数的功能就介绍完了。

此外还有很多技术细节没有深入研究,不过毕竟只是初探,就先讲到这里了,后续有时间再进一步深入研究。研究的时间还是比较短,如果有任何错误的地方欢迎指正。

参考资料

eBPF 简史 (下篇):

https://cloud.tencent.com/developer/article/1006318

goolge原生使用ebpf的两篇文章:

https://source.android.com/devices/architecture/kernel/bpf

https://source.android.com/devices/tech/datausage/ebpf-traffic-monitor

BCC:

https://github.com/iovisor/bcc

编辑:jq

原文标题:android平台eBPF初探

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
分享:

评论

相关推荐

MSK调制解调器的matlab仿真

继续讲解程序!MSK也能进行相干解调?是的!同样是采用锁相环!先来看看MSK的优点,这是由于下面的这....
的头像 通信工程师专辑 发表于 09-18 11:43 102次 阅读
MSK调制解调器的matlab仿真

介绍3种方法跨时钟域处理方法

跨时钟域处理是FPGA设计中经常遇到的问题,而如何处理好跨时钟域间的数据,可以说是每个FPGA初学者....
的头像 FPGA设计论坛 发表于 09-18 11:33 617次 阅读
介绍3种方法跨时钟域处理方法

机智云追踪外卖骑手保温箱硬件开发和项目演示

01 本章实现功能介绍 追踪外卖骑手的保温箱的GPS定位信息以及外卖箱是否被人打开,以防止骑手在送餐....
的头像 机智云开发者 发表于 09-18 11:03 103次 阅读

深入探究Linux系统噪音统计(osnoise tracer)

在Linux系统中作为一个普通线程是非常苦逼的。不仅NMI 、硬中断、软中断可以打断它,甚至其它普通....
的头像 Linux阅码场 发表于 09-18 10:53 143次 阅读
深入探究Linux系统噪音统计(osnoise tracer)

avr单片机INT0是如何去模拟代码的

avr单片机INT0是如何去模拟代码的?怎样去编写其代码?...
发表于 09-18 06:49 0次 阅读

三菱交流伺服系统伺服故障和报警代码

伺服故障和报警代码大全,超实用!使用三菱交流伺服系统主要由三个系列:MR-ES、MR-J2S、MR-J3。通常故障情况可由伺服...
发表于 09-17 08:54 0次 阅读

如何利用51单片机制作从左至右再从右制作的流水灯呢

如何利用51单片机制作从左至右再从右制作的流水灯呢?如何编写其代码程序?...
发表于 09-17 06:52 0次 阅读

松下伺服报警代码保护功能

《松下伺服故障报警代码分析及处理》由会员分享,可在线阅读,更多相关《松下伺服故障报警代码分析及处理(2页珍藏版)》请在人人文...
发表于 09-17 06:20 0次 阅读

​开发板上玩GTA RISC-V多项移植项目成功运作中

电子发烧友网报道(文/周凯扬)RISC-V近期再度掀起了不小的热度,苹果招募RISC-V程序员负责其....
的头像 电子发烧友网 发表于 09-16 11:59 140次 阅读
​开发板上玩GTA RISC-V多项移植项目成功运作中

嵌入式开发中实用的宏打印函数

宏打印函数在我们的嵌入式开发中,使用printf打印一些信息是一种常用的调试手段。但是,在打印的信息....
的头像 FPGA之家 发表于 09-16 10:05 98次 阅读
嵌入式开发中实用的宏打印函数

使用Kotlin替代Java重构AOSP应用

两年前,Android 开源项目 (AOSP) 应用团队开始使用 Kotlin 替代 Java 重构....
的头像 谷歌开发者 发表于 09-16 09:26 101次 阅读
使用Kotlin替代Java重构AOSP应用

声级频率计权的基本定义

1、声级频率计权声级频率计权的基本定义是指其恒幅稳态正弦输入信号级与显示装置上指示信号级两者之间作为频率函数关系而规定的差...
发表于 09-16 08:39 0次 阅读

es6语法中函数参数

es6语法中函数参数 本文在我们的《 实用ES6》 一书中有介绍 。 深入了解ES6中引入的新语言功能。  ES6引入了Ar...
发表于 09-16 08:17 0次 阅读

实现步进电机运动

目前做一个项目遇到一个问题,就是在实现步进电机运动时,点动模式电机振动很厉害,现在就一个非常强大的第三方库Accelstepper进...
发表于 09-16 07:34 0次 阅读

用ES6编写JavaScript函数

这篇文章是在我们的书,功能 实用ES6 。 获取的ES6引入的新的语言特性的深刻理解。  箭功能用ES6引入作为编写J...
发表于 09-16 06:40 0次 阅读

魔方网表,无代码开发平台NCDP的无冕之王

NCDP也就是No-code development platform,无代码开发平台,我第一次听到....
的头像 话说科技 发表于 09-15 14:34 85次 阅读

C语言中struct的用法有哪些

定义结构体变量       下面举一个例子来说明怎样定义结构体变量。                ....
的头像 STM32嵌入式开发 发表于 09-15 09:41 667次 阅读

51单片机的启动文件作用是什么

在我们使用kei c51创建一个51单片机项目时,会有如下图所示的提示: 一般情况下,需要选择“是”....
的头像 嵌入式ARM 发表于 09-15 09:12 181次 阅读
51单片机的启动文件作用是什么

如何充分利用Heroku CI

ci/cd heroku 持续集成和持续交付(CI / CD)是当今软件工程开发过程中的最佳实践。  持续集成 (CI)允许开发人...
发表于 09-15 08:43 0次 阅读

代码生成有哪些用途

代码生成有许多用途:  我们可以从模式或现有信息源中生成重复代码。 例如,我们可以从数据库模式文件生成数据访问对象...
发表于 09-15 08:04 0次 阅读

ROS中导航功能包里路径规划A*算法中步骤和代码详解

一、下载编译功能包   cd ~/catkin_ws/srcsudo apt-get install....
发表于 09-13 16:49 1015次 阅读

FastThreadLocal快在哪里

blog.csdn.net/mycs2012/article/details/90898128 1 ....
的头像 Android编程精选 发表于 09-13 09:17 132次 阅读

C++基础语法友元类和友元函数

本期是C++基础语法分享的第五节,今天给大家来分享一下: (1)explicit(显式)关键字; (....
的头像 C语言编程学习基地 发表于 09-12 09:52 190次 阅读

一条SQL语句是怎么被执行的

一直是想知道一条SQL语句是怎么被执行的,它执行的顺序是怎样的,然后查看总结各方资料,就有了下面这一....
的头像 Linux爱好者 发表于 09-12 09:44 168次 阅读
一条SQL语句是怎么被执行的

如何通过Python脚本实现WIFI密码的暴力破解

前言 本文将记录学习下如何通过 Python 脚本实现 WIFI 密码的暴力破解,从而实现免费蹭网。....
的头像 马哥Linux运维 发表于 09-10 17:09 323次 阅读
如何通过Python脚本实现WIFI密码的暴力破解

北鲲云超算平台助推生物制药行业发展

随着科技进步,生物制药正在被视为改写人类命运的关键。北鲲云超算平台蛋白设计助推生物制药行业发展,提供....
发表于 09-10 14:15 30次 阅读

软件工程师为什么要写文档

在大多数软件工程师对编写、使用和维护代码的抱怨中,一个常见的问题是缺乏高质量的文档。缺乏文档有什么副....
的头像 Linux阅码场 发表于 09-09 11:26 249次 阅读

使用deepstream-test的范例代码修改车牌识别与遮盖

前一篇文章提到使用deepstream-test的范例代码,修改成“车牌识别”与“遮盖(redact....
的头像 NVIDIA英伟达企业解决方案 发表于 09-09 10:04 176次 阅读
使用deepstream-test的范例代码修改车牌识别与遮盖

在STM32G4片内不同存储空间运行的速度差异

最近有人问起程序在STM32G4片内不同存储空间运行的速度差异。说实在的,这个很难说死或说出个绝对的....
的头像 茶话MCU 发表于 09-09 09:57 235次 阅读
在STM32G4片内不同存储空间运行的速度差异

C++基础语法之inline 内联函数

上节我们分析了C++基础语法的const,static以及 this 指针,那么这节内容我们来看一下....
的头像 C语言编程学习基地 发表于 09-09 09:38 152次 阅读

如何使用C++语法中的volatile

volatile volatile int i = 10; volatile 关键字是一种类型修饰符....
的头像 C语言编程学习基地 发表于 09-09 09:38 214次 阅读

C++语法中的inline内联函数详解

上节我们分析了C++基础语法的const,static以及 this 指针,那么这节内容我们来看一下....
的头像 C语言编程学习基地 发表于 09-09 09:33 1019次 阅读

骑手保温箱追踪及温湿度监测4G设备接入机智云教程

01 前言 利用机智云提供的通用版App即使不懂云和App开发,也可以在不用写任何代码的情况下,轻松....
的头像 机智云开发者 发表于 09-09 09:16 147次 阅读
骑手保温箱追踪及温湿度监测4G设备接入机智云教程

Kitronik ARCADE游戏手柄实现连连看

连连看相信大家都玩过,但这个用Kitronik AR CADE游戏手柄来玩连连看的项目你相信是一个高....
的头像 电子森林 发表于 09-08 11:47 223次 阅读
Kitronik ARCADE游戏手柄实现连连看

函数信号发生器的功能及优势

函数信号发生器是一种信号发生装置,能产生某些特定的周期性时间函数波形 ( 正弦波、方波、三角波、锯齿....
发表于 09-08 11:35 98次 阅读

如何把Docker Registry迁移到Harbor

“要如何将 docker registry 中的镜像迁移至 harbor?本文介绍了四种具体的思路和....
的头像 马哥Linux运维 发表于 09-07 16:29 300次 阅读
如何把Docker Registry迁移到Harbor

最为精简的一个Linux Fork炸弹解析

转自:http://blog.saymagic.cn/2015/03/25/fork-bomb.ht....
的头像 Linux爱好者 发表于 09-07 16:12 115次 阅读

使用Intellij IDEA的一些小技巧

https://blog.csdn.net/linsongbin1/article/details/....
的头像 Android编程精选 发表于 09-05 15:03 318次 阅读

内联汇编代码中的关键语法规则讲解

一、基本 asm 格式 1. 语法规则 2. test1.c 插入空指令 3. test2.c 操作....
的头像 硬件攻城狮 发表于 09-05 09:46 227次 阅读

Spark SQL的概念及查询方式

一、Spark SQL的概念理解 Spark SQL是spark套件中一个模板,它将数据的计算任务通....
的头像 数据分析与开发 发表于 09-02 15:44 180次 阅读
Spark SQL的概念及查询方式

C语言代码中的extern

在你的C语言代码中,不知能否看到类似下面的代码: 这好像没有什么问题,你应该还会想:“嗯⋯是啊,我们....
的头像 STM32嵌入式开发 发表于 09-02 15:13 205次 阅读
C语言代码中的extern

你们知道指针和引用正确的使用场景吗

先解决两个疑问 ◆ 指针和引用的不同之处是什么? ◆ 何时用用指针?何时用引用? 指针和引用的不同之....
的头像 STM32嵌入式开发 发表于 09-02 14:37 180次 阅读
你们知道指针和引用正确的使用场景吗

Vivado调用Questa Sim或ModelSim仿真小技巧

Vivado调用Questa Sim或ModelSim仿真中存在的一些自动化问题的解决方案。 Viv....
的头像 FPGA之家 发表于 09-02 10:12 203次 阅读
Vivado调用Questa Sim或ModelSim仿真小技巧

比Arduino更简单易用的开发套件ShineBlink

Hi 机友们,我想向你推荐一个小而美的产品,一个比Arduino更简单易用的开发套件——ShineB....
的头像 机智云物联网 发表于 09-02 10:04 578次 阅读

为什么要进行单相机标定

为什么要进行单相机标定? 广义:畸变矫正和一维和二维测量 畸变矫正: 在几何光学和阴极射线管(CRT....
的头像 新机器视觉 发表于 09-02 09:45 213次 阅读

Go编译器已默认启用-G=3支持泛型

Go 项目代码仓库昨日提交和合并的一个 PR 显示,Go 语言已在 cmd/compile 中默认启....
的头像 马哥Linux运维 发表于 09-01 15:52 1210次 阅读
Go编译器已默认启用-G=3支持泛型

分享一个最新的的Python对象序列化方式

许多Python标准库都有一些未被赏识的精华。其中之一是允许简单优雅的基于参数类型的函数分发。这一特....
的头像 马哥Linux运维 发表于 09-01 15:19 674次 阅读
分享一个最新的的Python对象序列化方式

Go常用的加密算法详细解读

【导读】本文介绍了常用的加密算法,并对这些加密算法结合实际 golang 代码段进行了详细解读。 前....
的头像 开关电源芯片 发表于 09-01 14:47 127次 阅读

一文透析Nginx-ingress 控制器如何实现的

主机nginx 一般nginx做主机反向代理(网关)有以下配置 upstream order{ se....
的头像 Linux爱好者 发表于 09-01 14:44 869次 阅读
一文透析Nginx-ingress 控制器如何实现的

代码中是数学图像解法和贪心解法

今天讲一个贪心的老司机的故事,就是力扣第 134 题「加油站」: 题目应该不难理解,就是每到达一个站....
的头像 新材料在线 发表于 09-01 14:14 197次 阅读
代码中是数学图像解法和贪心解法

如何才能够翻转二叉树

这道题目是非常经典的题目,也是比较简单的题目(至少一看就会)。 但正是因为这道题太简单,一看就会,一....
的头像 新材料在线 发表于 09-01 11:45 221次 阅读

Python 代码加速运行的的小技巧

Python 是一种脚本语言,相比 C/C++ 这样的编译语言,在效率和性能方面存在一些不足。但是,....
的头像 Android编程精选 发表于 09-01 11:28 245次 阅读

K8S集群服务访问失败怎么办 K8S故障处理集锦

问题1:K8S集群服务访问失败?     原因分析:证书不能被识别,其原因为:自定义证书,过期等。 ....
的头像 开关电源芯片 发表于 09-01 11:11 248次 阅读
K8S集群服务访问失败怎么办 K8S故障处理集锦

ADI-blackfin-PPI驱动TFT屏的代码-TFT-Init

ADI-blackfin-PPI驱动TFT屏的代码-TFT-Init(电源技术投稿模版)-ADI-b....
发表于 08-31 11:28 22次 阅读
ADI-blackfin-PPI驱动TFT屏的代码-TFT-Init