本文地址:https://www.ebpf.top/post/ubuntu_2104_bpf_env
Vagrant 是一款用于构建及配置虚拟开发环境的软件,基于 Ruby,主要以命令行的方式运行。Vagrant 由 HashiCorp 官方出品,相信提到大名鼎鼎的 HashiCorp 公司,大家还能够联想到著名的安全密码存储 Valut、服务注册发现 Consul、大规模调度系统 Normad 等等。
Vagrant 可基于官方提供的各种虚拟机打包文件(比如 VirtualBox 的 Box 文件)快速搭建各种系统的验证环境,也可以灵活通过配置式的文件管理多 VM 环境,同时具有平台适配性,是非常好的 VM 管理工具。但其自身并不提供虚拟化环境,需要配合 VirtualBox、WMware、KVM 等虚拟化技术,1.6 版本底层也支持使用容器,可以将容器替代完整的虚拟系统。
Vagrant 的架构使用 "Provisioners" 和 "Providers" 作为开发环境的构建模块。
讯享网
Vagrant 作为最外层的虚拟软件,目的是帮助开发者更容易地与 Providers 互动。Vagrantfile 记录 Providers 和 Provisioners 的相关信息。
Providers 作为服务,帮助 vagrant 使用 Boxes 建立和创建虚拟环境。Vagrant 提供的内嵌的 Provider 有 VirtualBox、Hyper-V、Docker、VMware 等。
在 Mac 系统中如果使用 Brew 管理包,则可以通过 brew 命令直接安装。其他系统的安装方式可参考 下载 Vagrant,查看详情。
讯享网
在安装 vagrant 成功后,我们还需要安装底层的虚拟化软件(即上述架构中的 Providers)才能正常工作,这里我们使用 VirtualBox。
Oracle VirtualBox 是德国公司 InnoTek 出品的虚拟机软件,现在由 Oracle 公司管理和发行,适用于多平台系统。用户可以在 VirtualBox 上安装并且运行 Solaris/Windows/Linux 等系统作为客户端操作系统。
在 Mac 系统上可以通过下载 dmg 文件进行安装。其他系统的安装参见 Oracle VM VirtualBox 基础包 。
在 Vagrant 和 VirtualBox 安装完成后,我们可以使用以下命令快速搭建一个 Ubuntu 的 VM:
在启动成功后,我们可以通过 直接登录到 VM 系统中。
2021 年 4 月 22 号,Ubuntu 发布了 21.04 Hirsute Hippo 版本 ,内核采用 5.11.0 版本。这里选择最新的 Ubuntu 发行版本,主要考虑 BPF 技术演进较快,新功能基本都需要高版本内核,采用最新发行的 Ubuntu 发行版本,方便后续的 BPF 功能学习和内核版本升级。更多 Ubuntu 版本发布的详情可参见官方 Wiki。
这里我们使用 Vagrant 虚拟机的方式快速搭建环境,Hirsute Box 镜像 可在官方提供的 Vagrant Boxs 市场 中查询,ubuntu/hirsute64 Box 的镜像大小为 600M 左右。
讯享网
如果从国外下载镜像过慢,可以通过其他方式下载 Box 文件,使用命令: 然后导入到本地后再启动上述命令。为方便大家快速下载我已经上传了一份到 百度网盘 ,提取码【bgfg】。
另外,我们也可以使用以下命令将正在运行的 VM 重新打包成 Box 文件:
讯享网
如果上述安装顺利,我们可以通过 ssh 的方式登录到新创建的 VM 机器中。
通过检查 内核编译选项确认系统是否已经支持 BTF 能力,这是 BPF CO-RE (Compile Once – Run Everywhere) 能力的基础。
讯享网
至此,我们的 BPF VM 环境已基本准备完成。
对于我们编译 BPF 程序而言需要系统已经安装了必备的 linux-headers 包。在 Ubuntu/Debian/Arch/Manjaro 发行版系统中需要安装 linux-headers 包,而在 CentOS/Fedora 发行版系统中需要安装 kernel-headers 和 kernel-devel 两个包。
首先我们在 VM 中安装 linux-headers 包:
如果是通过内核升级版本的场景,务必确认 linux-headers 版本与当前运行的内核版本一致。
为了能够编译 BPF 程序,我们还需要安装编译所依赖的工具包:
讯享网
通过上述 clang/llvm 版本信息查看,我们可以知道在 Ubuntu 21.04 版本中,安装的为 12.0 的版本,这可以满足我们对于 CO-RE 能力的要求(>= 9.0 版本)。
我们使用 libbpf-bootstrap 来进行编译验证,同时使用 参数将 libbpf-bootstrap 仓库中的依赖子模块 libbpf 同时下载到本地。
如没有错误提示,且通过下述的 ls 命令可查看到对应的二进制文件,则表明编译成功。
讯享网
至此我们可以将 VM 导出为 Box 文件以便作为后续的基础,需要在 VM Vagrant 文件所在的目录操作运行,导出过程会自动关闭 VM 虚拟机。
ubuntu_21_04_bpf.box 文件已经上传 百度云盘 ,提取码【if2j】,文件大小 1.1G。
安装 Ubuntu 21.04 源代码,并解压源代码:
讯享网
源码编译 sample/bpf 模块:( 为方便编译,统一切换成 root 用户 )
在 samples/bpf 目录包含接近 60 个相关的程序,给与我们学习提供了便利,同时也提供了一个组织编译的 Makefile 框架。如果我们用 C 语言编写的 BPF 程序编译可以直接在该目录提供的环境中进行编译。
如果是需要单独编译的场景,也可以参考 BCC 仓库中的 libbpf-tools 下的样例。
samples/bpf 下的程序一般组成方式是 xyz_user.c 和 xyz_kern.c:
- xyz_user.c 为用户空间的程序用于设置 BPF 程序的相关配置、加载 BPF 程序至内核、设置 BPF 程序中的 map 值和读取 BPF 程序运行过程中发送至用户空间的消息等。目前 xyz_user.c 与 xyz_kern.c 程序在交互实现都是基于 bpf() 系统调用完成的。直接使用 bpf() 系统调用涉及的参数和细节比较多,使用门槛较高,因此为了方便用户空间程序更加易用,内核提供了 libbpf 库封装了对于 bpf() 系统调用的细节。
- xyz_kern.c 为 BPF 程序代码,通过 clang 编译成字节码加载至内核中,在对应事件触发的时候运行,可以接受用户空间程序发送的各种数据,并将运行时产生的数据发送至用户空间程序。
完整的样例代码参见 hello_world_bpf_ex。
hello_user.c
讯享网
hello_kern.c
Makefile 文件修改
讯享网
在当前目录重新运行 make 命令即可。编译完成后,启动命令后在其他窗口执行 ,显示效果如下:
mainline 为 Ubuntu 提供可视化的内核升级工具,早期版本为 ukuu 。该工具支持的特性如下:
- 从 Ubuntu Mainline PPA 中获取可用的内核列表
- 当有新的内核更新时,可以选择观察并显示通知
- 自动下载和安装软件包
- 方便地显示可用和已安装的内核
- 从界面上安装 / 卸载内核
- 对于每个内核,相关的软件包(头文件和模块)会同时安装或卸载
使用 Vagrant 快速搭建一个 VM 环境:
讯享网
可以通过以下命令自动安装:
list 子命令会显示出来当前系统支持升级的或者已经安装的系统:
讯享网
通过上述输出我们也可以看出,和手工安装的过程类似,同样需要 4 个主要文件,( 手动安装可以到 http://kernel.ubuntu.com/~kernel-ppa/mainline/ 这里下载 ):
- linux-headers-5.14.7-051407-generic_5.14.7-051407.0_amd64.deb(通用头文件) 和 amd64/linux-headers-5.14.7-051407_5.14.7-051407.0_all.deb(基础头文件)
- amd64/linux-image-unsigned-5.14.7-051407-generic_5.14.7-051407.0_amd64.deb
- amd64/linux-modules-5.14.7-051407-generic_5.14.7-051407.0_amd64.deb
在本次升级到 5.14.7 的过程中,modules 和 linux images 成功,但是安装 linux-headers-5.14.7-051407-generic 头文件的时候,遇到了以下的问题:
错误提示的大意是我们安装的 linux-headers-5.14.7-051407 需要 libc 的版本 >= 2.34,而我们系统的 libc 版本为 2.33。而 linux-headers 是我们 BPF 需要的环境 linux-headers,所以还需要手动修复安装。
讯享网
系统重启后已经证明我们成功升级了系统,这里我们继续手工修复 linux-headers 问题,首先尝试使用手工安装:
错误提示我们使用 来修订错误,该命令其实做的事情就是删除存在问题的头文件包:
讯享网
从网上搜索 libc-2.34 版本的安装包 ,下载并安装:
到 Ubunt 5.14.7 主线 下载安装出错的 linux-headers-5.14.7-051407-generic,然后手工进行安装:
讯享网
这种强制安装的 pkg 的方式,会影响到其他依赖包的管理,一般不推荐。 这种情况一般是我们升级的内核版本比较新,其他的对应组件还未能完全更新。如果是升级到 Ubuntu 的官方新发布版本(比如从 20.04 升级到 21.04),建议通过官方提供的方式升级,内核和其他依赖包都可以一起升级,保证整体完整型,可参考 如何升级到 Ubuntu 20.04。
某些情况我们需要更新版本的内核,如果 Ubuntu 官方还未提供该版本的安装包及内核源码,那么我们就需要通过源码编译和安装的方式进行。本文从 Ubuntu 环境中编译,其他的 Linux 发行版可以参考 内核源码编译指南 。
5.2.1 源码下载及编译工具安装
基于 Ubuntu 21.04 的系统,我们从 内核网站 上选择 5.14.7 版本进行编译。
安装必要的内核编译工具:
讯享网
Linux BTF 功能需要 pahole 工具 (>= 1.16) ,该工具位于 dwarves 包中,需要提前进行安装。
5.2.2 源码编译
编译前需要将系统中运行的 config 文件复制到内核编译目录中为 .config 文件。
讯享网
因为当前目录已经存在 .config 文件,make menuconfig 会直接使用 .config 作为默认值,通过图形界面修改值以后,默认会将当前的 .config 备份成 .config.old,并生成新的 .config 文件。
这里如果采用 make oldconfig,那么则是通过命令界面配置内核,会自动载入既有的 .config 配置文件,并且只有在遇到先前没有设定过的选项时,才会要求我们手动设定。同样也会将老的 .config 备份成 .config.old 文件。
运行 make 命令编译, -j 参数可指定并行 CPU 核数:
如果编译过程中遇到 的错误,可以通过禁用证书或者将运行系统中源码的相关证书复制到当前目录下的 debian 目录。
方案 1:复制系统中的证书
将当前运行系统源码中的 /usr/src/linux-source-5.11.0/debian/canonical-certs.pem 和 /usr/src/linux-source-5.11.0/debian/canonical-revoked-certs.pem 复制到当前 debian 目录中:
讯享网
方案 2:采用禁用 SYSTEM_TRUSTED_KEYS 的方式
待证书设置以后,就可以运行 make 命令进行编译。
编译的时长使用的 CPU 核数相关,编译大概占用 20G 左右的产品空间。
5.2.3 内核安装和启动选择
编译成功后,使用以下命令安装内核:
讯享网
reboot 重启后,我们使用使用 uname 查看,发现系统内核已经更新为了 5.14.7 版本。
Ubuntu 21.04 采用 GRUB2 来管理启动菜单,对应的文件为 /boot/grub/grub.cfg ,该文件为 update-grub 命令依据 /etc/default/grub 文件自动生成。如果需要调整菜单选项,这需要通过 /etc/default/grub 文件修改,然后通过运行 update-grub 命令生效。
/etc/default/grub 文件中的:
GRUB_DEFAULT 指定了默认启动的菜单选项,0 表示第一个菜单选项。
GRUB_TIMEOUT 选项表明了启动菜单显示的时间,方便用于用户选择,默认为 0,在调试新的内核时建议设置成一个非 0 值,同时需要将 GRUB_TIMEOUT_STYLE 的值从 hidden 调整为 menu:
讯享网
然后通过 update-grub 命令更新生效,再重新启动就可以看到启动菜单。其他参数详细配置可参见 Grub 配置 。
todo: 在 VirtualBox 中能看到停顿,但是未能够看到启动界面
5.2.4 其他 - 编译内核以后磁盘管理
Virtualbox 底层使用 vmdk 的磁盘格式,当前会存在只是单向增大不会自动收缩的问题(即使我们在编译内核后,删除了编译相关的问题),请参见 VirtualBox VM 空间瘦身记(vmdk)。
- Ubuntu 21.04 is here

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/186665.html