网易首页 > 网易号 > 正文 申请入驻

从零开始的内核eBPF之旅(1)

0
分享至

引言

内核研究与开发是计算机底层处于与硬件打交道的部位,ebpf可以理解为是内核开发的一个模块。在研究ebpf开发之前需要对计算机的一些基础知识学习了解,懂得计算机的基本组成和操作系统的基本原理和运行机制,了解Linux内核设计的机制和相关源码的阅读与理解,再深入内核模块观察ebpf的设计思路,进而做到对ebpf的开发与实现。

在此之前,首先需要储备一些基本的计算机知识。

基础知识储备

计算机组成原理

学习计算机组成原理可以对计算机的基础架构有所理解,了解计算机中常见的术语和概念。

操作系统

操作系统作为人和计算机交互的桥梁,理解其工作原理对后续内核开发有很好的帮助,对操作系统的术语了解知道其背后的道理是开发的基础。

C语言

C语言是Linux内核开发主要使用的编程语言和开发工具,需要熟悉其基本语法和结构。

Linux基础

了解Linux基本组成和常用的shell命令,熟悉Linux的文件架构。

FHS(Filesystem Hierarchy Standard):

FHS依据文件系统使用的频繁与否与是否允许使用者随意更动, 而将目录定义成为四种交互作用的形态,用表格来说有点像底下这样:

• 可分享的:可以分享给其他系统挂载使用的目录,所以包括执行文件与用户的邮件等数据,是能够分享给网络上其他主机挂载用的目录;

• 不可分享的:自己机器上面运作的装置文件或者是与程序有关的socket文件等, 由于仅与自身机器有关,所以当然就不适合分享给其他主机了。

• 不变的:有些数据是不会经常变动的,跟随着distribution而不变动。例如函式库、文件说明文件、系统管理员所管理的主机服务配置文件等等;

• 可变动的:经常改变的数据,例如登录文件、一般用户可自行收受的新闻组等。

事实上,FHS针对目录树架构仅定义出三层目录底下应该放置什么数据而已,分别是底下这三个目录的定义:

1. / (root, 根目录):与开机系统有关;

2. /usr (unix software resource):与软件安装/执行有关;

3. /var (variable):与系统运作过程有关.

根目录 (/)的意义与内容:

概要:

4. 所有的目录都是由根目录衍生出来的(根目录是整个系统最重要的一个目录)

5. 与开机/还原/系统修复等动作有关。(由于系统开机时需要特定的开机软件、核心文件、开机所需程序、 函式库等等文件数据,若系统出现错误时,根目录也必须要包含有能够修复文件系统的程序才行)

6. FHS标准建议:根目录(/)所在分割槽应该越小越好,且应用程序所安装的软件最好不要与根目录放在同一个分割槽内,保持根目录越小越好。(因为越大的分割槽妳会放入越多的数据,如此一来根目录所在分割槽就可能会有较多发生错误的机会,如此不但效能较佳,根目录所在的文件系统也较不容易发生问题。)

根目录(/)底下目录FHS定义的说明:

除上FHS中定义的目录说明外,底下是几个在Linux当中非常重要的目录:

不可与根目录分开的目录(与开机过程有关):

根目录与开机有关,开机过程中仅有根目录会被挂载,其他分割槽则是在开机完成之后才会持续的进行挂载的行为。就是因为如此,因此根目录下与开机过程有关的目录,就不能够与根目录放到不同的分割槽去!

• /etc:配置文件

• /bin:重要执行档

• /dev:所需要的装置文件

• /lib:执行档所需的函式库与核心所需的模块

• /sbin:重要的系统执行文件

/usr的意义与内容:

概要:

7. 依据FHS的基本定义,/usr里面放置的数据属于可分享的与不可变动的(shareable, static),如果你知道如何透过网络进行分割槽的挂载,那么/usr确实可以分享给局域网络内的其他主机来使用!

8. usr(Unix Software Resource即Unix操作系统软件资源) FHS建议所有软件开发者,应该将他们的数据合理的分别放置到这个目录下的次目录,而不要自行建立该软件自己独立的目录。

9. 所有系统默认的软件(distribution发布者提供的软件)都会放置到/usr底下,因此这个目录有点类似Windows系统的『C:\Windows\ + C:\Program files\』这两个目录的综合体,系统刚安装完毕时,这个目录会占用最多的硬盘容量。

一般来说,/usr的次目录建议有底下这些:

/var的意义与内容:

概要:

/var目录主要针对常态性变动的文件,包括缓存(cache)、登录档(log file)以及某些软件运作所产生的文件,包括程序文件(lock file, run file),或者例如MySQL数据库的文件等等。所以/var在系统运作后才会渐渐占用硬盘容量的目录

常见的次目录有:

针对FHS,各家distributions的异同:

由于FHS仅是定义出最上层(/)及次层(/usr, /var)的目录内容应该要放置的文件或目录数据,,因此,在其他次目录层级内,就可以随开发者自行来配置了。举例来说,CentOS的网络设定数据放在/etc/sysconfig/network-scripts/目录下,但是SuSE则是将网络放置在/etc/sysconfig/network/目录下,目录名称可是不同的呢!不过只要记住大致的FHS标准,差异性其实有限啦!

Linux 命令大全查询表

Linux内核

Linux内核学习策略

Linux学习建议配套远古版本的Linux内核源码学习,有助于帮助理解内核设计的思路,下载并阅读Linux内核1.0版本的源码去学习,该版本基本包含了内核基本部件,后续的版本都是在此基础上扩充功能,但是基本的内在没有变化。

内核源码不同版本间的阅读与对比可参考Bootlin,其中1.0源码目录结构如下,其中对主要文件目录进行解释:

对照着内核设计的源代码进行学习,会从根源上思考这样设计的目的是什么。

Linux内核开发环境配置

内核开发环境和源码安装配置:Linux内核开发环境配置

Linux内核简介

Linux 内核的用途是什么?

Linux 内核有 4 项工作:

10. 内存管理:追踪记录有多少内存存储了什么以及存储在哪里

11. 进程管理:确定哪些进程可以使用中央处理器(CPU)、何时使用以及持续多长时间

12. 设备驱动程序:充当硬件与进程之间的调解程序/解释程序

13. 系统调用和安全防护:从流程接受服务请求

在正确实施的情况下,内核对于用户是不可见的,它在自己的小世界(称为内核空间)中工作,并从中分配内存和跟踪所有内容的存储位置。用户所看到的内容(例如 Web 浏览器和文件)则被称为用户空间。这些应用通过系统调用接口(SCI)与内核进行交互。

举例来说,内核就像是一个为高管(硬件)服务的忙碌的个人助理。助理的工作就是将员工和公众(用户)的消息和请求(进程)转交给高管,记住存放的内容和位置(内存),并确定在任何特定的时间谁可以拜访高管、会面时间有多长。

Linux内核学习路线和框架图

Linux Security Coachin

Linux内核基础学习资料

Linux内核与系统驱动保护入口

该视频资料详细介绍了Linux内核的知识点及其在内核中的实现进行比对,很有参考价值。

MakeFile详解

Makefile 可以简单的认为是一个工程文件的编译规则,描述了整个工程的编译和链接等规则。详细介绍如下:

MakeFile详解

Makefile文件负责编写程序的编译与运行规则,免去命令行使用Clang去逐步编译分析。

GDB详解

GDB是一个强大的调试工具,通过它可以实现C程序代码bug的调试。

GDB详解

Linux崩溃调试

Linux内核Crash下的问题解决方案:

Linux调试之崩溃

EBPF基础

什么是ebpf?

Linux 内核一直是实现监控/可观测性、网络和安全功能的理想地方。不过很多情况下这并非易事,因为这些工作需要修改内核源码或加载内核模块, 最终实现形式是在已有的层层抽象之上叠加新的抽象。

eBPF 是一项革命性技术,它能在内核中运行沙箱程序(sandbox programs), 而无需修改内核源码或者加载内核模块。

eBPF 催生了一种全新的软件开发方式。基于这种方式,我们不仅能对内核行为进行 编程,甚至还能编写跨多个子系统的处理逻辑,而传统上这些子系统是完全独立、 无法用一套逻辑来处理的。

安全:

观测和理解所有的系统调用的能力,以及在 packet 层和 socket 层审视所有的网络操作的能力, 这两者相结合,为系统安全提供了革命性的新方法。以前,系统调用过滤、网络层过滤和进程上下文跟踪是在完全独立的系统中完成的;eBPF 的出现统一了可观测性和各层面的控制能力,使我们有更加丰富的上下文和更精细的控制能力, 因而能创建更加安全的系统。

网络:

eBPF 的两大特色 —— 可编程和高性能 —— 使它能满足所有的网络包处理需求。可编程意味着无需离开内核中的包处理上下文,就能添加额外的协议解析器或任何转发逻辑, 以满足不断变化的需求。高性能的 JIT 编译器使 eBPF 程序能达到几乎与原生编译的内核态代码一样的执行性能。

跟踪 & 性能分析:

eBPF 程序能够加载到 trace points、内核及用户空间应用程序中的 probe points, 这种能力使我们对应用程序的运行时行为(runtime behavior)和系统本身 (system itself)提供了史无前例的可观测性。应用端和系统端的这种观测能力相结合, 能在排查系统性能问题时提供强大的能力和独特的信息。BPF 使用了很多高级数据结构, 因此能非常高效地导出有意义的可观测数据,而不是像很多同类系统一样导出海量的原始采样数据。

观测 & 监控:

相比于操作系统提供的静态计数器(counters、gauges),eBPF 能在内核中收集和聚合自定义 metric, 并能从不同数据源来生成可观测数据。这既扩展了可观测性的深度,也显著减少了整体系统开销, 因为现在可以选择只收集需要的数据,并且后者是直方图或类似的格式,而非原始采样数据。

Linux驱动模块开发

简介

Linux 内核的整体结构已经非常庞大,而其包含的组件也非常多。这会导致两个问题,一是生成的内核会很大,二是如果我们要在现有的内核中新增或删除功能,将不得不重新编译内核。Linux 提供了这样的一种机制,这种机制被称为模块(Module)。使得编译出的内核本身并不需要包含所有功能,而在这些功能需要被使用的时候,其对应的代码被动态地加载到内核中。

举例

先来看一个最简单的内核模块“Hello World”,代码如下:

#include #include static int hello_init(void) /初始化函数/{printk(KERN_INFO " Hello World enter\n");return 0;}static void hello_exit(void) /卸载函数/{printk(KERN_INFO " Hello World exit\n ");}module_init(hello_init); /模块初始化/module_exit(hello_exit); /卸载模块/MODULE_LICENSE("Dual BSD/GPL"); /许可声明/MODULE_AUTHOR("Linux");MODULE_DESCRIPTION("A simple Hello World Module");MODULE_ALIAS("a simplest module");

这个模块定义了两个函数, 一个在模块加载到内核时被调用( hello_init )以及一个在模块被去除时被调用( hello_exit ). moudle_init 和 module_exit 这几行使用了特别的内核宏来指出这两个函数的角色. 另一个特别的宏 (MODULE_LICENSE) 是用来告知内核, 该模块带有一个自由的许可证.

注:内核模块中用于输出的函数是内核空间的 printk()而非用户空间的 printf(),具体用法参考附件 printk函数介绍。

几个常用命令

加载模块

通过“insmod ./hello.ko”命令可以加载,加载时输出“Hello World enter”。

卸载模块

通过“rmmod hello”命令可以卸载,卸载时输出“Hello World exit”。

查看系统中已经加载的模块列表

在Linux中,使用lsmod命令可以获得系统中加载了的所有模块以及模块间的依赖关系,例如:

root@imx6:~$ lsmodModule Size Used byhello 1568 0ohci1394 32716 0ide_scsi 16708 0ide_cd 39392 0cdrom 36960 1 ide_cd

查看某个具体模块的详细信息

使用modinfo <模块名>命令可以获得模块的信息,包括模块作者、模块的说明、模块所支持 的参数以及 vermagic:

root@imx6:~$ modinfo hello.kofilename: hello.kolicense: Dual BSD/GPLauthor: Song Baohuadescription: A simple Hello World Modulealias: a simplest modulevermagic: 2.6.15.5 686 gcc-3.2depends:

Linux 内核模块程序的结构

一个Linux内核模块主要由如下几个部分组成:

1、模块加载函数(一般需要) 当通过insmod或modprobe命令加载内核模块时,模块的加载函数会自动被内核执行,完成本模块的相关初始化工作。

2、模块卸载函数(一般需要) 当通过rmmod命令卸载某模块时,模块的卸载函数会自动被内核执行,完成与模块卸载函数相反的功能。

3、模块许可证声明(必须) 许可证(LICENSE)声明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将收到内核被污染 (kernel tainted)的警告。在Linux 2.6内核中,可接受的LICENSE包括“GPL”、“GPL v2”、“GPL and additional rights”、“Dual BSD/GPL”、“Dual MPL/GPL”和“Proprietary”。大多数情况下,内核模块应遵循GPL兼容许可权。Linux 2.6内核模块最常见的是以

MODULE_LICENSE( “Dual BSD/GPL” )语句声明模块采BSD/GPL双LICENSE。

4、模块参数(可选)模块参数是模块被加载的时候可以被传递给它的值,它本身对应模块内部的全局变量。

5、模块导出符号(可选)内核模块可以导出符号(symbol,对应于函数或变量),这样其它模块可以使用本模块中的变量或函数。

6、模块作者等信息声明(可选)用于申明模块作者的相关信息,一般用于备注作者姓名、邮箱等。

模块加载函数

Linux 内核模块加载函数一般以_ _init 标识声明,典型的模块加载函数如下:

static int _ _init initialization_function(void){/* 初始化代码 */}module_init(initialization_function);

模块加载函数必须以“module_init(函数名)”的形式被指定。它返回整型值,若初始化成功,应返回 0。而在初始化失败时,应该返回错误编码。在 Linux 内核里,错误编码是一个负值。

在 Linux 2.6 内核中,可以使用 request_module(const char *fmt, …)函数加载内核模块,驱动开发人员可以通过调用。

request_module(module_name);/**** 或者 ****/request_module("char-major-%d-%d", MAJOR(dev), MINOR(dev));

注意:在 Linux 中,所有标识为_ init 的函数在连接的时候都放在.init.text 这个区段内,此外,所有的 init 函数在区段.initcall.init 中还保存了一份函数指针,在初始化时内核会通过这些函数指针调用这些 _init 函数,并在初始化完成后,释放 init 区段(包括.init.text、.initcall.init 等)。

模块卸载函数

static void _ _exit cleanup_function(void){/* 释放代码 */}module_exit(cleanup_function);

模块卸载函数在模块卸载的时候执行,不返回任何值,必须以“module_exit(函数名)”的形式来指定。通常来说,模块卸载函数要完成与模块加载函数相反的功能,如下所示。

若模块加载函数注册了 XXX,则模块卸载函数应该注销 XXX。

若模块加载函数动态申请了内存,则模块卸载函数应释放该内存。

若模块加载函数申请了硬件资源(中断、DMA 通道、I/O 端口和 I/O 内存等)的占用,则模块卸载函数应释放这些硬件资源。

若模块加载函数开启了硬件,则卸载函数中一般要关闭之。

模块参数

用“module_param(参数名,参数类型,参数读/写权限)”为模块定义一个参数,例如下列代码定义了 1 个整型参数和 1 个字符指针参数:

static char *book_name = " dissecting Linux Device Driver ";static int num = 4 000;module_param(num, int, S_IRUGO);module_param(book_name, charp, S_IRUGO);

参数类型可以是 byte、short、ushort、int、uint、long、ulong、charp(字符指针)、bool 或 invbool(布尔的反),在模块被编译时会将 module_param 中声明的类型与变量定义的类型进行比较,判断是否一致。

在装载内核模块时,用户可以向模块传递参数,形式为“insmode(或 modprobe)模块名 参数名=参数值”,如果不传递,参数将使用模块内定义的缺省值。

内核模块的符号导出

模块可以使用如下宏导出符号到内核符号表:

EXPORT_SYMBOL(符号名);

EXPORT_SYMBOL_GPL(符号名);

导出的符号将可以被其他模块使用,使用前声明一下即可。EXPORT_SYMBOL_GPL()只适用于包含 GPL 许可权的模块。

模块声明与描述

在Linux内核模块中,我们可以用MODULE_AUTHOR、MODULE_DESCRIPTION、MODULE_VERSION、MODULE_DEVICE_TABLE、MODULE_ALIAS分别声明模块的作者、描述、版本、设备表和别名,

例如:

MODULE_AUTHOR(author);MODULE_DESCRIPTION(description);MODULE_VERSION(version_string);MODULE_DEVICE_TABLE(table_info);MODULE_ALIAS(alternate_name);

对于USB、PCI等设备驱动,通常会创建一个MODULE_DEVICE_TABLE。

MakeFile

Kernel modules

obj-m += hello.o

Specify flags for the module compilation.

#EXTRA_CFLAGS=-g -O0build: kernel_moduleskernel_modules:make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules #modules表示编译成模块的意思#CURDIR是make的内嵌变量,自动设置为当前目录clean:make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean

该 Makefile 文件应该与源代码 hello.c 位于同一目录,开启其中的 EXTRA_CFLAGS=-g -O0可以得到包含调试信息的 hello.ko 模块。运行 make 命令得到的模块可直接在 PC 上运行。

注:uname 的更多用法详见附件

如果一个模块包括多个.c 文件(如 file1.c、file2.c),则应该以如下方式编写 Makefile:

obj-m := modulename.omodulename-objs := file1.o file2.o

obj-m是个makefile变量,它的值可以是一串.o文件的表列

EBPF详解(未完待续)

本篇主要叙述了ebpf的学习过程,后面我们还将继续分享ebpf详细学习笔记和记录。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
新的历史纪录!黄金价格突破5000美元,机构看多到6600美元

新的历史纪录!黄金价格突破5000美元,机构看多到6600美元

21世纪经济报道
2026-01-26 07:12:18
恐怖20-0!澳网第2位前八种子出局 萨巴伦卡创历史 王欣瑜目标8强

恐怖20-0!澳网第2位前八种子出局 萨巴伦卡创历史 王欣瑜目标8强

侃球熊弟
2026-01-26 00:20:03
太丢脸了!一男子武汉理工毕业,当保安月薪3800元,称被学校约谈

太丢脸了!一男子武汉理工毕业,当保安月薪3800元,称被学校约谈

火山诗话
2026-01-24 12:25:19
贾国龙最新发声!“将回归一线,不再打造个人IP”

贾国龙最新发声!“将回归一线,不再打造个人IP”

每日经济新闻
2026-01-25 22:13:09
菲律宾客船倾覆事故已致7人死亡

菲律宾客船倾覆事故已致7人死亡

界面新闻
2026-01-26 07:10:13
172:233!高市早苗重新洗牌,日新首相人选出炉,对华态度不简单

172:233!高市早苗重新洗牌,日新首相人选出炉,对华态度不简单

梁讯
2026-01-25 19:18:01
父死女偿!一银行放贷30万,独生女破釜沉舟,彻底给银行整不会了

父死女偿!一银行放贷30万,独生女破釜沉舟,彻底给银行整不会了

火山诗话
2026-01-25 12:21:40
委内瑞拉新政府宣布不承认马杜罗及其所有债务

委内瑞拉新政府宣布不承认马杜罗及其所有债务

桂系007
2026-01-25 23:56:17
董路登上日本网站热搜榜第一,日本网友:中国足球专家何时成熟?

董路登上日本网站热搜榜第一,日本网友:中国足球专家何时成熟?

杨华评论
2026-01-25 20:51:07
同方股份原总裁、董事长陆致成去世,曾推动组建清华同方股份有限公司并上市

同方股份原总裁、董事长陆致成去世,曾推动组建清华同方股份有限公司并上市

红星资本局
2026-01-25 15:21:52
委内瑞拉被扣油轮上的石油已被取出,特朗普:正在加工!委代总统:马杜罗被抓后,美方称“给我们15分钟,不配合就杀了我们”

委内瑞拉被扣油轮上的石油已被取出,特朗普:正在加工!委代总统:马杜罗被抓后,美方称“给我们15分钟,不配合就杀了我们”

每日经济新闻
2026-01-25 23:15:09
大冷!广厦无缘30分逆转遭山东终结7连胜 布朗38分末节21分

大冷!广厦无缘30分逆转遭山东终结7连胜 布朗38分末节21分

醉卧浮生
2026-01-25 21:34:49
何超琼没想到,倒贴嫁东北小伙的何超盈,如今竟给她狠狠长脸

何超琼没想到,倒贴嫁东北小伙的何超盈,如今竟给她狠狠长脸

白面书誏
2026-01-25 14:44:04
掉下去必死!31岁美国男子徒手攀爬台北101:91分钟登顶 看着都怕

掉下去必死!31岁美国男子徒手攀爬台北101:91分钟登顶 看着都怕

风过乡
2026-01-25 17:36:53
希曼:不理解阿尔特塔为何同时换下4人,比赛节奏直接乱了

希曼:不理解阿尔特塔为何同时换下4人,比赛节奏直接乱了

懂球帝
2026-01-26 07:15:49
日本为何禁肉1200年?乃是统治者“制度设计”,解禁后人均身高迅速上涨

日本为何禁肉1200年?乃是统治者“制度设计”,解禁后人均身高迅速上涨

齐天候
2026-01-25 23:29:25
“留学一年嘴都变大了”,女学生面相变化图走红,牢A果然权威

“留学一年嘴都变大了”,女学生面相变化图走红,牢A果然权威

泽泽先生
2026-01-25 21:55:27
天助曼城:2-3,英超领头羊遭曼联逆转,3轮不胜,仅领先曼城4分

天助曼城:2-3,英超领头羊遭曼联逆转,3轮不胜,仅领先曼城4分

侧身凌空斩
2026-01-26 03:36:53
特殊的制度:不能连续任元首,盘点不得连选连任元首的15个国家

特殊的制度:不能连续任元首,盘点不得连选连任元首的15个国家

梦沉古道
2026-01-24 21:50:03
下周预期要大涨!这五大题材周末发酵   将助力指数上攻4200点

下周预期要大涨!这五大题材周末发酵 将助力指数上攻4200点

元芳说投资
2026-01-25 21:29:55
2026-01-26 07:43:00
安全客 incentive-icons
安全客
有思想的安全新媒体
1360文章数 4753关注度
往期回顾 全部

科技要闻

黄仁勋在上海逛菜市场,可能惦记着三件事

头条要闻

英首相将时隔8年访华 斯塔默:前几任不去中国是失职

头条要闻

英首相将时隔8年访华 斯塔默:前几任不去中国是失职

体育要闻

中国足球不会一夜变强,但他们已经创造历史

娱乐要闻

央八开播 杨紫胡歌主演的40集大剧来了

财经要闻

隋广义等80人被公诉 千亿骗局进入末路

汽车要闻

别克至境E7内饰图曝光 新车将于一季度正式发布

态度原创

房产
时尚
手机
数码
教育

房产要闻

正式官宣!三亚又一所名校要来了!

看了鲁豫对章小蕙的采访,最大感触是这一点

手机要闻

三星 Galaxy S26 系列配色、外观全曝光

数码要闻

新一代 Siri 或将随 iOS 26.4 测试版亮相

教育要闻

许昌学院王牌专业盘点!快速锁定报考目标

无障碍浏览 进入关怀版