目录
1 BiscuitOS 基础使用
2 BiscuitOS 软件开发
1.1 BiscuitOS 介绍
BiscuitOS 项目皆在实现一键部署 Linux 开发环境,源码编译直接运行。目前支持 linux 0.x、1.x、2.x、3.x、4.x、5.x 以及最新 6.x 内核, 架构方面全量支持 Intel X86_64 以及部分支持 i386、ARM、ARM64、RISCV32 以及 RISCV64 架构. BiscuitOS 项目制作的 Linux 称为 BiscuitOS 发行版, 其包含了 ROOTFS、BUSYBOX、Linux 内核以及第三方开源软件,另外 BiscuitOS 项目使用 QEMU 作为底座,可模拟定制化硬件、也可以直接在 X86 机器上运行. BiscuitOS 为开发者带来六大功能:
功能一: BiscuitOS 社区 为 BiscuitOS 项目提供了巨量的实践文档,包括 BiscuitOS 构建、内存管理、文件系统、虚拟化、基础研究等上百篇实践文档,均基于 BiscuitOS 实践进行简介,让理论和实践最佳结合。
功能二: BiscuitOS 提供了便捷的 Linux 源码查看、编译、调试工具,并提供特定场景的代码,可以边查看 Linux 源码,边对源码进行修改并进行实践,加上 ChatGPT 的加持,让开发者学习 Linux 事半功倍!
功能三: BiscuitOS 支持很多 Linux 内核版本的一键部署,例如最早的 Linux 0.11 内核、最新的 Linux 内核,基于覆盖了所有的 Linux 内核版本,另外还支持 X86 架构、i386 架构、ARM 架构、ARM64 架构以及 RISCV 架构,除此之外还包括对 Debian 特殊版本、Uboot、RaspberryPi、Apollo1、MIT-XV6 以及 SeaBIOS 开发环境的一键部署.
功能四: BiscuitOS 项目提供了丰富的开源软件,既包括应用程序、游戏、内核模块,也包括动态库、调试工具等。所有软件均可使用一键部署功能,轻松实现软件的部署、编译和使用.
功能五: BiscuitOS 项目可以对硬件进行模拟,可支持对 DMA、PCI、PCIe、IOMMU、MMIO、PIO、MSIX、PMEM、DMA-BUF、DMA-POOL、HMM、NUMA 以及 CXL 的实践,另外 Broiler 项目更大自由度的多硬件定制和模拟,开发者不用再为实践而花费购买昂贵硬件,另外开发者可以自定义 BiscuitOS 运行系统的硬件,例如内存大小、CPU 数量、以及不同文件系统的磁盘, 这些在 BiscuitOS 点点手指硬件环境一键部署.
功能六: BiscuitOS 项目提供了特殊的调试工具,可以精准调试: 缺页异常、SWAP OUT/IN 一个物理页、一次完整的系统调用、异步 DROP CACHE 一个 PAGE CACHE、跟踪一次 MMIO 虚拟化完整链路等,这些调试工具可以帮助开发者降低复杂场景的实践难度,加速对新知识的认知.
1.2 BiscuitOS 安装
BiscuitOS 项目维护在 Github 仓库 和 Gitee 仓库, 项目全部代码都是开源的. 由于 BiscuitOS 基于 QEMU 运行,因此需要一台 X86 机器作为开发机,开发机目前支持的版本如下:
- Ubuntu20.04 (推荐!完整支持)
- Ubuntu18.04 (完整支持)
- Ubuntu22.04 (完整支持)
- Ubuntu14.04 (支持)
- Windows+VirtualBox+Ubuntu(部分功能受限)
- Windows+WMware+Ubuntu(部分功能受限)
- Windows+WSL+Ubuntu(部分功能受限)
- CentOS (适配中)
- Debian (适配中)
- ArchLinux (适配中)
准备好一台开发机之后,开发者根据使用不同发行版需要提前安装开发工具,这些工具主要用于项目的下载和部署前期的准备,参考如下代码:
基础开发软件安装完毕之后,接下来从 Github/Gitee 上下载 BiscuitOS 项目源码,开发者为了加快下载速度可以使用 depth 参数,如果想看所有的代码提交,需要一定时间下载,参考如下代码:
- arch 目录是架构相关的配置
- board 目录是 BiscuitOS 支持硬件开发板相应的配置
- boot 是 BiscuitOS 系统使用的 BOOTLOAD 相关的配置
- config 目录下是 BiscuitOS 项目支持的部署开发环境
- dl 目录是 BiscuitOS 项目部署过程中下载的源码压缩包
- fs 目录是 BiscuitOS 使用的文件系统配置
- kernel 目录是 BiscuitOS 部署内核相关的配置
- package 目录是 BiscuitOS 支持的开源软件库配置
- scripts 目录是 BiscuitOS 部署过程中使用的脚本
- toolchain 目录是 BiscuitOS 部署使用的交叉编译工具配置
- output 目录是 BiscuitOS 部署不同版本 Linux 开发环境的位置
BiscuitOS 项目里的目录大部分都是配置相关的,里面可能只包含一些 Kconfig 文件和 Makefile 文件,这些文件用户控制整个部署过程。由于 BiscuitOS 是基于 Kbuild 构建,那么可以使用 config 下面的配置文件直接部署 Linux 环境,也可以图形化的配置部署过程. 如果开发者是第一次部署, 那么需要执行如下命令完成开发工具的安装:
基础环境安装完毕之后,那么接下来就是部署 Linux 开发环境了,开发者可以在 configs 目录下选择一个进行部署,configs 目录里面全部是某个架构指定 Linux 的部署配置,例如选择 linux-6.0-x86_64_defconfig, 名字中的 6.0 部署表示 Linux 源码版本是 Linux 6.0,名字中的 x86_64 字段指明部署的架构是 X86-64 架构,开发者使用如下命令:
命令执行完毕之后,BiscuitOS 项目将部署基于 X86-64 架构的 Linux 6.0 源码开发环境,如果开发者还想添加其他开源软件一同部署,那么可以直接使用命令开启图形化配置,与 Linux 内核的 Kbuild menuconfig 一致:
- Porject Name 选项指明开发环境在 output 目录下的名字
- Architecture configure 选项下面用于选择部署环境的架构
- Board setup 选项下面用于选择与模拟硬件相关的信息
- Bootloaders 选项下面用于选择 BiscuitOS 启动是采用的 Bootloader
- DIY BiscuitOS/Broiler Hardware 选项下面用于自定义 BiscuitOS 运行时的硬件
- package 选项下面用于添加第三方开源软件
- Root-Filesystem 选项下面用于配置 BiscuitOS 系统根文件系统的配置
- Compile toolchain 选项下面用于配置开发环境编译使用的交叉编译工具
- linux 用于配置 Linux 的版本.
上图是 Kbuild 图形化配置界面,当开发者使用了 “make linux-6.0-x86_64_defconfig” 命令之后,Kbuild 已经自动配置上图相关的配置,开发者可以根据自己的需要进行修改。修改完毕之后使用如下命令进行一键部署:
部署完毕之后,开发者会看到 4 条信息,第一条信息指明了 Linux 开发环境的位置; 第二条信息指明 Linux 源码的位置; 第三条信息指明 Linux 开发手册; 第四条是 BiscuitOS 社区的链接. 接下来进入开发环境所在的目录,BiscuitOS 里所有的开发环境均放在 output 目录下:
- Broiler-system: Broiler 目录支持自定义硬件模拟
- busybox: BiscuitOS 系统使用的 BUSYBOX 源码目录
- FreezeDir: BiscuitOS 系统数据盘挂载目录
- HardStack.BS: 里面 BiscuitOS 代码仓库配置文件
- Hardware: BiscuitOS 模拟的硬件,包括磁盘、内存等
- linux: Linux 源码目录
- package: 第三方开源软件目录
- qemu-system: BiscuitOS 模拟底座 QEMU 源码目录
- README.md: 开发环境说明文档
- rootfs: BiscuitOS 系统使用的根文件系统
- RunBiscuitOS.sh: BiscuitOS 运行脚本
BiscuitOS 一键部署的开发环境基本布局如上,其中 RunBiscuitOS.sh 是自动生成,只要在 BiscuitOS 项目顶层执行一次 make 命令,那么 RunBiscuitOS.sh 脚本就自动生成一次,脚本里面包含了 BiscuitOS 虚拟机启动的参数、硬件配置等. README.md 里描述了编译 Linux、Busybox 以及打包 ROOTFS 的命令,由于不同版本的 Linux 配置不同,无法将 README 里面的步骤自动化,因此开发者接下来需要参考 README.md 里面的内容完成最后的编译工作:
当执行完 README.md 里面的命令之后,可以启动 BiscuitOS,此时 BiscuitOS 系统作为一个虚拟机运行,开发者可以发挥自己的想象,任意修改 BiscuitOS 进行实践. 至此 BiscuitOS 安装成功!
2.1 部署应用程序
BiscuitOS 支持应用程序开发环境的一键部署和实践,免去了复杂的源码查找、编写、编译、打包等操作,开发者可以参考如下步骤在 BiscuitOS 上实践应用程序, 首先使用 BiscuitOS 部署应用程序,其部署逻辑如下:
应用程序开发环境的目录结构如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍,BiscuitOS-Application-default 目录下 “make download” 下载源码之后生成的,其中 main.c 是应用程序的源码, Makefile 是 main.c 编译文件,开发者可以根据自身需求修改编译过程,假如已经编译过源码,BiscuitOS-Application-default 是编译生成的可执行文件,最终在 BiscuitOS 上运行.
当 BiscuitOS 运行之后,直接运行 BiscuitOS-Application-default 应用程序,可以看到应用程序按预期打印了字符串。有了上面的应用程序开发环境之后,开发者可以发挥自己的想象修改 main.c 源码,并使用上面命令在 BiscuitOS 实践验证, 如果开发者觉得验证过程中需要输入很多命令才能启动 BiscuitOS,开发者可以在修改并保存代码之后,直接使用 make build 命令进行一键验证,直接提高实践效率。BiscuitOS 应用程序开发环境一共为开发者提供了如下命令:
- make: 编译应用程序
- make install: 安装应用程序
- make pack: 重新打包 BiscuitOS 系统的 ROOTFS
- make run: 运行 BiscuitOS
- make build: 一键验证应用程序
- make clean: 清除编译文件
- make distclean: 清空源码
- make download: 下载源码
- make kernel: 编译内核
- make broiler: 将应用程序打包到 Broiler
- make rootfs_install: 将应用程序打包到嵌套 BiscuitOS 系统里
2.2 部署内核模块
BiscuitOS 支持内核模块的一键部署和实践,免去了复杂的源码查找、编写、编译、打包等操作,开发者可以参考如下步骤在 BiscuitOS 上实践内核模块, 首先使用 BiscuitOS 部署内核模块,其部署逻辑如下:
内核模块开发环境的目录结构如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍,BiscuitOS-module-default 目录下 “make download” 下载源码之后生成的,其中 main.c 是内核模块的源码, Makefile 是 main.c 编译文件,Makefile.host 是在 Host 直接编译的文件,RunBiscuitOS.sh 文件是在 BiscuitOS 运行之后,一键运行模块相关的所有命令,开发者可以向该文件里添加需要运行的命令. 开发者可以根据自身需求修改编译过程,假如已经编译过源码,BiscuitOS-module-default.ko 是编译生成的 KO 文件,最终在 BiscuitOS 上加载运行.
当 BiscuitOS 运行之后,使用 insmod 命令加载内核模块,内核模块位于 “/lib/modules/$(uname -r)/extra/” 目录下,可以看到模块正确加载并打印预期的字符串,开发者如果想加快模块的安装,可以在系统运行之后,直接运行 RunBiscuitOS.sh,其会运行所需的命令。有了上面的内核模块开发环境之后,开发者可以发挥自己的想象修改 main.c 源码,并使用上面命令在 BiscuitOS 实践验证, 如果开发者觉得验证过程中需要输入很多命令才能启动 BiscuitOS,开发者可以在修改并保存代码之后,直接使用 make build 命令进行一键验证,直接提高实践效率。BiscuitOS 应用程序开发环境一共为开发者提供了如下命令:
- make: 编译应用程序
- make install: 安装应用程序
- make pack: 重新打包 BiscuitOS 系统的 ROOTFS
- make run: 运行 BiscuitOS
- make build: 一键验证应用程序
- make clean: 清除编译文件
- make distclean: 清空源码
- make download: 下载源码
- make kernel: 编译内核
- make broiler: 将应用程序打包到 Broiler
- make rootfs_install: 将应用程序打包到嵌套 BiscuitOS 系统里
2.3 部署内核 INITCALL 程序
BiscuitOS 支持内核 INITCALL 程序的一键部署和实践,免去了复杂的源码查找、编写、编译、打包等操作。在 Linux 启动过程中,会使用 INITCALL 机制按顺序启动内核子系统,那么 BiscuitOS 支持将程序嵌入到内核,并在指定的 INITCALL 之后运行,这可以大大提高对内核功能的验证. 开发者可以参考如下步骤在 BiscuitOS 上实践内核 INITCALL 程序, 首先使用 BiscuitOS 部署内核 INITCALL 程序,其部署逻辑如下:
内核 INITCALL 程序开发环境的目录结构如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍,KRunBiscuitOS.sh 做调试过滤信息使用,后面调试章节会详细介绍. BiscuitOS-kernel-default 目录下 “make download” 下载源码之后生成的,其中 main.c 是内核 INITCALL 程序的源码, Makefile 是 main.c 编译文件,Kconfig 是内核宏定义文件. 开发者可以修改 main.c 源文件里的 XXX_initcall 函数,以此确认程序运行的时机,最后在 BiscuitOS 上加载运行.
BiscuitOS 系统启动过程中,INITCALL 程序就会自动运行,开发者可以在 BiscuitOS 运行之后,使用 dmesg 查看启动 LOG,从中找出 INITCALL 程序运行的足迹,上图可以看出 INITCALL 程序已经正确执行。有了上面的内核 INITCALL 程序开发环境之后,开发者可以发挥自己的想象修改 main.c 源码,并使用上面命令在 BiscuitOS 实践验证, 如果开发者觉得验证过程中需要输入很多命令才能启动 BiscuitOS,开发者可以在修改并保存代码之后,直接使用 make build 命令进行一键验证,直接提高实践效率。BiscuitOS 应用程序开发环境一共为开发者提供了如下命令:
- make: 编译应用程序
- make install: 安装应用程序
- make pack: 重新打包 BiscuitOS 系统的 ROOTFS
- make run: 运行 BiscuitOS
- make build: 一键验证应用程序
- make clean: 清除编译文件
- make distclean: 清空源码
- make download: 下载源码
- make kernel: 编译内核
- make broiler: 将应用程序打包到 Broiler
- make rootfs_install: 将应用程序打包到嵌套 BiscuitOS 系统里
开发者有没有发现,每次编译内核 INITCALL 程序的时候,都会重新编译一次内核,因此可以将内核 INITCALL 程序开发环境作为内核编译的接口,直接使用 “make build” 命令就可以快速编译和实践内核.
2.4 部署内核 AnyWhere 程序
BiscuitOS 支持将一段独立程序嵌入到内核任何位置的一键部署和实践,免去了复杂的源码查找、编写、编译、打包等操作。BiscuitOS 通过提供一段段独立的模块化代码,用于对内核特定阶段的代码进行实践,这将大大增加 BiscuitOS 对内核的可实践度, 这也是 BiscuitOS 特殊功能之一,开发者可以参考如下步骤在 BiscuitOS 进行部署和实践,其部署逻辑如下:
内核 AnyWhere 程序开发环境的目录结构如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍. BiscuitOS-kernel-any-default 目录下 “make download” 下载源码之后生成的,其中 main.c 是内核 AnyWhere 程序的源码, Makefile 是 main.c 编译文件,Kconfig 是内核宏定义文件, BiscuitOS_Insert.bs 是一个配置文件,用于配置 AnyWhere 程序在内核中运行的位置:
在 BiscuitOS_Insert.bs 配置文件中,[Content] 下一个描述 AnyWhere 程序中需要插入的函数名字, [File] 下一行描述 AnyWhere 函数插入位置所在的文件,[Func] 下一行描述 AnyWhere 函数插入文件里指定函数之后一行,例如上图的意思是将 main.c 文件中的 BiscuitOS_Running() 函数插入到 Linux 源码 init/main.c 文件里 setup_arch() 函数之后. 开发者需要注意插入文件中只有一个 [Func] 指向的函数. 最后在 BiscuitOS 上加载运行.
BiscuitOS 系统启动过程中,AnyWhere 程序会在指定位置运行,开发者可以在 BiscuitOS 运行之后,使用 dmesg 查看启动 LOG,从中找出 AnyWhere 程序运行的足迹,上图可以看出 AnyWhere 程序已经正确执行。有了上面的内核 AnyWhere 程序开发环境之后,开发者可以发挥自己的想象修改 main.c 源码,并使用上面命令在 BiscuitOS 实践验证, 如果开发者觉得验证过程中需要输入很多命令才能启动 BiscuitOS,开发者可以在修改并保存代码之后,直接使用 make build 命令进行一键验证,直接提高实践效率。BiscuitOS 应用程序开发环境一共为开发者提供了如下命令:
- make: 编译应用程序
- make install: 安装应用程序
- make pack: 重新打包 BiscuitOS 系统的 ROOTFS
- make run: 运行 BiscuitOS
- make build: 一键验证应用程序
- make clean: 清除编译文件
- make distclean: 清空源码
- make download: 下载源码
- make kernel: 编译内核
- make broiler: 将应用程序打包到 Broiler
- make rootfs_install: 将应用程序打包到嵌套 BiscuitOS 系统里
2.5 部署字符设备模块
BiscuitOS 支持字符设备相关的用户进程和内核模块一键部署和实践,免去了复杂的源码查找、编写、编译、打包等操作。BiscuitOS 通过提供一套完成的调用程序,充分使用字符设备提供的内核接口,可以快速部署字符设备的应用场景, 这也是 BiscuitOS 特殊功能之一,开发者可以参考如下步骤在 BiscuitOS 进行部署和实践,其部署逻辑如下:
字符设备开发环境的目录结构如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍. BiscuitOS-Char-default 目录下 “make download” 下载源码之后生成的,其中 main.c 是字符设备驱动的源码, app.c 是调用字符设备接口的应用程序,Makefile 是 main.c 编译文件,Kconfig 是内核宏定义文件, Makefile.host 是字符设备在主机上的编译脚本, RunBiscuitOS.sh 是实践案例运行的所有命令合集,最后在 BiscuitOS 上加载运行.
当 BiscuitOS 运行之后,使用 insmod 命令加载内核模块,内核模块位于 “/lib/modules/$(uname -r)/extra/” 目录下,可以看到模块正确加载并打印预期的字符串,接着运行应用程序 APP,可以看到应用程序与字符设备模块进行数据交互. 开发者如果想加快模块的安装,可以在系统运行之后,直接运行 RunBiscuitOS.sh,其会运行所需的命令。有了上面的内核模块开发环境之后,开发者可以发挥自己的想象修改 main.c 源码,并使用上面命令在 BiscuitOS 实践验证, 如果开发者觉得验证过程中需要输入很多命令才能启动 BiscuitOS,开发者可以在修改并保存代码之后,直接使用 make build 命令进行一键验证,直接提高实践效率。BiscuitOS 应用程序开发环境一共为开发者提供了如下命令:
- make: 编译应用程序
- make install: 安装应用程序
- make pack: 重新打包 BiscuitOS 系统的 ROOTFS
- make run: 运行 BiscuitOS
- make build: 一键验证应用程序
- make clean: 清除编译文件
- make distclean: 清空源码
- make download: 下载源码
- make kernel: 编译内核
- make broiler: 将应用程序打包到 Broiler
- make rootfs_install: 将应用程序打包到嵌套 BiscuitOS 系统里
2.6 部署 MISC 设备模块
BiscuitOS 支持 MISC 设备相关的用户进程和内核模块一键部署和实践,免去了复杂的源码查找、编写、编译、打包等操作。BiscuitOS 通过提供一套完成的调用程序,充分使用 MISC 设备提供的内核接口,可以快速部署 MISC 设备的应用场景, 这也是 BiscuitOS 特殊功能之一,开发者可以参考如下步骤在 BiscuitOS 进行部署和实践,其部署逻辑如下:
MISC 设备开发环境的目录结构如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍. BiscuitOS-MISC-default 目录下 “make download” 下载源码之后生成的,其中 main.c 是 MISC 设备驱动的源码, app.c 是调用 MISC 设备接口的应用程序,Makefile 是 main.c 编译文件,Kconfig 是内核宏定义文件, Makefile.host 是 MISC 设备在主机上的编译脚本, RunBiscuitOS.sh 是实践案例运行的所有命令合集,最后在 BiscuitOS 上加载运行.
当 BiscuitOS 运行之后,使用 insmod 命令加载内核模块,内核模块位于 “/lib/modules/$(uname -r)/extra/” 目录下,可以看到模块正确加载并打印预期的字符串,接着运行应用程序 APP,可以看到应用程序与 MISC 设备模块进行数据交互. 开发者如果想加快模块的安装,可以在系统运行之后,直接运行 RunBiscuitOS.sh,其会运行所需的命令。有了上面的内核模块开发环境之后,开发者可以发挥自己的想象修改 main.c 源码,并使用上面命令在 BiscuitOS 实践验证, 如果开发者觉得验证过程中需要输入很多命令才能启动 BiscuitOS,开发者可以在修改并保存代码之后,直接使用 make build 命令进行一键验证,直接提高实践效率。BiscuitOS 应用程序开发环境一共为开发者提供了如下命令:
- make: 编译应用程序
- make install: 安装应用程序
- make pack: 重新打包 BiscuitOS 系统的 ROOTFS
- make run: 运行 BiscuitOS
- make build: 一键验证应用程序
- make clean: 清除编译文件
- make distclean: 清空源码
- make download: 下载源码
- make kernel: 编译内核
- make broiler: 将应用程序打包到 Broiler
- make rootfs_install: 将应用程序打包到嵌套 BiscuitOS 系统里
2.7 部署 Platform 设备模块
BiscuitOS 支持 Platform 设备内核模块一键部署和实践,免去了复杂的源码查找、编写、编译、打包等操作。内核里有很多需要使用 Platform 的场景,BiscuitOS 可以快速部署 Platform 设备的应用场景, 这也是 BiscuitOS 特殊功能之一,开发者可以参考如下步骤在 BiscuitOS 进行部署和实践,其部署逻辑如下:
Platform 设备开发环境的目录结构如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍. BiscuitOS-Platform-default 目录下 “make download” 下载源码之后生成的,其中 main.c 是 Platform 设备驱动的源码, Makefile 是 main.c 编译文件,Kconfig 是内核宏定义文件, Makefile.host 是 MISC 设备在主机上的编译脚本, RunBiscuitOS.sh 是实践案例运行的所有命令合集,最后在 BiscuitOS 上加载运行.
当 BiscuitOS 运行之后,使用 insmod 命令加载内核模块,内核模块位于 “/lib/modules/$(uname -r)/extra/” 目录下,可以看到模块正确加载并打印预期的字符串. 开发者如果想加快模块的安装,可以在系统运行之后,直接运行 RunBiscuitOS.sh,其会运行所需的命令。有了上面的内核模块开发环境之后,开发者可以发挥自己的想象修改 main.c 源码,并使用上面命令在 BiscuitOS 实践验证, 如果开发者觉得验证过程中需要输入很多命令才能启动 BiscuitOS,开发者可以在修改并保存代码之后,直接使用 make build 命令进行一键验证,直接提高实践效率。BiscuitOS 应用程序开发环境一共为开发者提供了如下命令:
- make: 编译应用程序
- make install: 安装应用程序
- make pack: 重新打包 BiscuitOS 系统的 ROOTFS
- make run: 运行 BiscuitOS
- make build: 一键验证应用程序
- make clean: 清除编译文件
- make distclean: 清空源码
- make download: 下载源码
- make kernel: 编译内核
- make broiler: 将应用程序打包到 Broiler
- make rootfs_install: 将应用程序打包到嵌套 BiscuitOS 系统里
2.8 部署第三方开源软件
开发过程中进程需要使用第三方开源软件,例如 lspci、strace、numactl 等,BiscuitOS 支持第三方开源软件一键部署和实践,免去了复杂的源码查找、编写、编译、打包等操作,本节以 strace 开源软件为例进行讲解,开发者可以参考如下步骤在 BiscuitOS 进行部署和实践,其部署逻辑如下:
第三方开源软件下载之后需,一般以压缩包形式存在,有的是直接从 git 仓库下载下来,此时需要使用 “make tar” 命令进行源码解压。解压之后如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍. strace-5.0.tar.xz 是源码压缩包,第一次部署时 BiscuitOS 会从网上进行下载,下载还之后放在 BiscuitOS 项目的 dl 目录下,因此在离线场景中,可以先将源码压缩包放在 dl 目录下; strace-5.0 目录是解压之后的源码目录,最后编译源码并在 BiscuitOS 上运行:
当 BiscuitOS 运行之后,可以直接运行 strace 第三方开源软件,有了上面的第三方开发环境之后,开发者可以发挥自己的想象修改源码,并使用上面命令在 BiscuitOS 实践验证, 如果开发者觉得验证过程中需要输入很多命令才能启动 BiscuitOS,开发者可以在修改并保存代码之后,直接使用 make build 命令进行一键验证,直接提高实践效率。BiscuitOS 应用程序开发环境一共为开发者提供了如下命令:
- make: 编译应用程序
- make install: 安装应用程序
- make pack: 重新打包 BiscuitOS 系统的 ROOTFS
- make run: 运行 BiscuitOS
- make build: 一键验证应用程序
- make clean: 清除编译文件
- make distclean: 清空源码
- make download: 下载源码
- make kernel: 编译内核
- make broiler: 将应用程序打包到 Broiler
- make rootfs_install: 将应用程序打包到嵌套 BiscuitOS 系统里
- make prepare: 自动安装依赖库
2.9 部署共享库
开发过程中进程需要使用动态共享库,例如 libnuma、libelf、libz 等,BiscuitOS 支持开源共享库的一键部署和实践,免去了复杂的源码查找、编写、编译、打包等操作,本节以 libnuma 开源软件为例进行讲解,开发者可以参考如下步骤在 BiscuitOS 进行部署和实践,其部署逻辑如下:
开源动态库下载之后需,一般以压缩包形式存在,有的是直接从 git 仓库下载下来,此时需要使用 “make tar” 命令进行源码解压。解压之后如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍. 第一次部署时 BiscuitOS 会从网上进行下载,下载还之后放在 BiscuitOS 项目的 dl 目录下,因此在离线场景中,可以先将源码压缩包放在 dl 目录下; numactl-libnuma-default 目录是解压之后的源码目录,最后编译源码并在 BiscuitOS 上运行:
当 BiscuitOS 运行之后,可以在 /usr/lib 目录下查看 libnuma 相关的库,也可以直接使用 libnuma 开源项目提供的命令 numactrl 等,有了上面的动态库开发环境之后,开发者可以发挥自己的想象修改源码,并使用上面命令在 BiscuitOS 实践验证, 如果开发者觉得验证过程中需要输入很多命令才能启动 BiscuitOS,开发者可以在修改并保存代码之后,直接使用 make build 命令进行一键验证,直接提高实践效率。BiscuitOS 应用程序开发环境一共为开发者提供了如下命令:
- make: 编译应用程序
- make install: 安装应用程序
- make pack: 重新打包 BiscuitOS 系统的 ROOTFS
- make run: 运行 BiscuitOS
- make build: 一键验证应用程序
- make clean: 清除编译文件
- make distclean: 清空源码
- make download: 下载源码
- make kernel: 编译内核
- make broiler: 将应用程序打包到 Broiler
- make rootfs_install: 将应用程序打包到嵌套 BiscuitOS 系统里
- make prepare: 自动安装依赖库
2.10 快速配置、编译内核
BiscuitOS 项目是为内核开发而生,因此 BiscuitOS 集成了内核快速开发的命令,开发者可以参考本节实现内核的快速开发。首先开发者需要在 BiscuitOS 上部署内核开发工具集, 其部部署逻辑如下:
内核开发工具集的目录结构如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍,KRunBiscuitOS.sh 做调试过滤信息使用,后面调试章节会详细介绍. 接下来介绍工具集命令:
- make: 编译内核
- make menuconfig: 配置内核
- make install: 安装 KRunBiscuitOS.sh 脚本
- make pack: 重新打包 BiscuitOS 系统的 ROOTFS
- make run: 运行 BiscuitOS
- make build: 一键编译并运行内核
- make broiler: 将编译好的内核打包到 Broiler
- make rootfs_install: 将编译好的内核打包到嵌套 BiscuitOS 系统里
- make module: 编译内核模块
有了上面命令之后,开发者无需关系什么架构或者什么版本内核,直接使用上面的命令就可以实现内核快速编译,make build 命令更可一键实现编译加运行,大大提高了内核开发效率. make menuconfig 命令可以方便配置内核选项,make module 命令会编译出内核模块依赖文件,这会影响独立模块编译.
3. BiscuitOS DIY 硬件
3.1 修改内存大小
BiscuitOS 支持修改物理内存大小,其修改逻辑如下:
BiscuitOS 系统启动之后,可以看到系统物理内存已经变成了 4G.
3.2 修改 ROOTFS 大小
BiscuitOS 支持修改系统盘 ROOTFS 大小,其修改逻辑如下:
BiscuitOS 系统启动之后,使用 df 命令可以看到根目录 “/dev/root” 空间已经变成 467M(接近 500M),修改生效. 当开发者要注意,ROOTFS 越大,意味着打包 ROOTFS 所花费的时间就越多.
3.3 修改 CPU 数量
BiscuitOS 支持修改系使用的 CPU 数量,其修改逻辑如下:
BiscuitOS 系统启动之后,查看 “/proc/cpuinfo” 节点确认 CPU 数量,上图可以看出 CPU 数量为 2,修改生效.
3.4 添加内核 CMDLINE
BiscuitOS 支持添加内核 CMDLINE,其修改逻辑如下:
BiscuitOS 系统启动之后,查看 “/proc/cmdline” 节点可以看到内核正在使用的 CMDLINE,上图可以看出 “BiscuitOS=Ondemand” 字段,修改生效.
3.5 支持 NUMA 拓扑
BiscuitOS 支持添加 NUMA 拓扑结构,其修改逻辑如下:
BiscuitOS 系统启动之后,通过 “numactl” 命令可以查看系统 NUMA 拓扑结果,上图可以看出系统中存在两个 NUMA NODE,修改生效.
3.6 支持 CPU 特性直通
BiscuitOS 底层基于 QEMU 构建,因此在虚拟化场景或者某些特定场景下,需要直通 CPU 特性,其修改逻辑如下:
BiscuitOS 系统启动之后,通过查看 /proc/cpuinfo 节点可以看到 CPU 硬件信息,上图可以看到 Host CPU 与 BiscuitOS 里 CPU 信息一致,修改生效.
3.7 支持 Broiler 自定义硬件
Broiler 项目是为 BiscuitOS 量身定制的硬件模拟工具,其模拟了多种 DMA、PCI、PCIe、MSIX 等硬件设备和场景,为实践特殊场景提供了可能,其部署逻辑如下:
BiscuitOS 系统启动之后,自动加载 Broiler 继续运行,可以将 Broiler 理解为 BiscuitOS 系统里再启动一个 BiscuitOS,只是最终的 BiscuitOS 包含了很多特殊的硬件设备. Broiler 可以自定义很多硬件设备,甚至可以定义系统的物理地址空间布局,感兴趣的开发者可以参考:
3.8 添加一个只包含 BAR 的 PCIe 设备
BiscuitOS 支持对 PCIe 的实践,可以通过一键部署一个只带 BAR 的 PCIe 设备. 其部署逻辑如下:
BiscuitOS 系统启动之后,可以使用 lspci 命令看到 1016:1413 设备为刚刚加载的 PCIe 设备, 可以看到 PCIe 设备包含了两个 BAR,BAR0 映射到 IO Space 空间,范围是: [0xC000, 0xD000), BAR1 映射到系统物理地址空间,其范围是: [0xFEBF1000m 0xFEBF2000), 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:
第一次部署
通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-QEMU-DEVICE-BAR-default 拷贝到 QEMU 源码目录下,参考如下命令:
上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:
可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备 1016:1413, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:
BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,开发者可以直接看到实践案例的结果,提高执行的效率.
3.9 添加一个支持 INTX 中断的 PCIe 设备
BiscuitOS 支持对 PCIe 的实践,可以通过一键部署一个带 INTX 中断的 PCIe 设备. 其部署逻辑如下:
BiscuitOS 系统启动之后,可以使用 lspci 命令看到 1016:1991 设备为刚刚加载的 PCIe 设备, 可以看到 PCIe 设备包含了一个 BAR,BAR0 映射到 IO Space 空间,范围是: [0xC0C0, 0xC0E0), 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:
第一次部署
通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-QEMU-DEVICE-INTX-default 拷贝到 QEMU 源码目录下,参考如下命令:
上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:
可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备 1016:1991, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:
BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,并且收到 PCIe 设备的 INTX 中断 IRQ11. 开发者可以直接看到实践案例的结果,提高执行的效率.
3.10 添加一个支持 MSI 中断的 PCIe 设备
BiscuitOS 支持对 PCIe 的实践,可以通过一键部署一个带 MSI 中断的 PCIe 设备. 其部署逻辑如下:
BiscuitOS 系统启动之后,可以使用 lspci 命令看到 1001:1991 设备为刚刚加载的 PCIe 设备, 可以看到 PCIe 设备包含了一个 BAR,BAR0 映射到 IO Space 空间,范围是: [0xC0C0, 0xC0E0), 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:
第一次部署
通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-QEMU-DEVICE-MSI-default 拷贝到 QEMU 源码目录下,参考如下命令:
上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:
可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备 1001:1991, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:
BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,并且收到 PCIe 设备的 MSI 中断 IRQ26. 开发者可以直接看到实践案例的结果,提高执行的效率.
3.11 添加一个支持 MSIX 中断的 PCIe 设备
BiscuitOS 支持对 PCIe 的实践,可以通过一键部署一个带 MSIX 中断的 PCIe 设备. 其部署逻辑如下:
BiscuitOS 系统启动之后,可以使用 lspci 命令看到 1002:1991 设备为刚刚加载的 PCIe 设备, 可以看到 PCIe 设备包含了一个 BAR,BAR0 映射到 IO Space 空间,范围是: [0xC0C0, 0xC0E0), 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:
第一次部署
通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-QEMU-DEVICE-MSIX-default 拷贝到 QEMU 源码目录下,参考如下命令:
上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:
可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备 1002:1991, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:
BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,并且收到 PCIe 设备的 MSI 中断 IRQ26. 开发者可以直接看到实践案例的结果,提高执行的效率.
3.12 添加一个支持 INTX/DMA 中断的 PCIe 设备
BiscuitOS 支持对 PCIe 的实践,可以通过一键部署一个带 DMA/INTX 中断的 PCIe 设备. 其部署逻辑如下:
BiscuitOS 系统启动之后,可以使用 lspci 命令看到 0309:1989 设备为刚刚加载的 PCIe 设备, 可以看到 PCIe 设备包含了一个 BAR,BAR0 映射到 IO Space 空间,范围是: [0xC0C0, 0xC0E0), 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:
第一次部署
通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-DMA-QEMU-DEVICE-INTX-default 拷贝到 QEMU 源码目录下,参考如下命令:
上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:
可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备 0309:1989, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:
BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,并且收到 PCIe 设备的 INTX 中断 IRQ11, 最后通过 DMA 读取到字符串. 开发者可以直接看到实践案例的结果,提高执行的效率.
3.13 添加一个支持 MSI 中断的 PCIe 设备
BiscuitOS 支持对 PCIe 的实践,可以通过一键部署一个带 DMA/MSI 中断的 PCIe 设备. 其部署逻辑如下:
BiscuitOS 系统启动之后,可以使用 lspci 命令看到 1024:1991 设备为刚刚加载的 PCIe 设备, 可以看到 PCIe 设备包含了一个 BAR,BAR0 映射到 IO Space 空间,范围是: [0xC0C0, 0xC0E0), 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:
第一次部署
通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-DMA-QEMU-DEVICE-MSI-default 拷贝到 QEMU 源码目录下,参考如下命令:
上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:
可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备 1024:1991, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:
BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,并且通过 DMA 搬运从设备获得字符串. 开发者可以直接看到实践案例的结果,提高执行的效率.
3.14 添加一个支持 DMA/MSIX 中断的 PCIe 设备
BiscuitOS 支持对 PCIe 的实践,可以通过一键部署一个带 DMA/MSIX 中断的 PCIe 设备. 其部署逻辑如下:
BiscuitOS 系统启动之后,可以使用 lspci 命令看到 1002:1991 设备为刚刚加载的 PCIe 设备, 可以看到 PCIe 设备包含了一个 BAR,BAR0 映射到 IO Space 空间,范围是: [0xC0C0, 0xC0E0), 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:
第一次部署
通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-DMA-QEMU-DEVICE-MSIX-default 拷贝到 QEMU 源码目录下,参考如下命令:
上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:
可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备 1026:1991, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:
BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,并从设备 DMA 搬运内容进行了打印. 开发者可以直接看到实践案例的结果,提高执行的效率.
3.15 添加一个支持 DMA-BUF 的设备
BiscuitOS 支持对 DMA-BUF 的实践,DMA-BUF 主要解决多个外设之间共享内存的问题,可以通过一键部署多个设备实现 DMA-BUF 场景. 其部署逻辑如下:
BiscuitOS 系统启动之后,可以使用 lspci 命令看到: EXPORTER 1018:1991, IMPORTA: 1019:1991, IMPORTB: 101A:1991, 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:
第一次部署
通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-DMA-BUF-QEMU-DEVICE-default 拷贝到 QEMU 源码目录下,参考如下命令:
上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:
可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备: EXPORTER 1018:1991, IMPORTA: 1019:1991, IMPORTB: 101A:1991, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:
BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,并可以看到 Exportor 生产的数据被 Importor 消费了. 开发者可以直接看到实践案例的结果,提高执行的效率.
3.16 添加一个支持 IOMMU 的设备
BiscuitOS 支持对 IOMMU 的实践,IOMMU 要解决的其中一个问题外设可以映射不连续的物理内存. BiscuitOS 可以通过一键部署对 IOMMU 支持. 其部署逻辑如下:
BiscuitOS 系统启动之后,从 dmesg 中查看 IOMMU 相关的初始化信息,另外直接运行 RunBiscuitOS.sh 可以运行基于 IOMMU 的 DMA 搬运,上图可以看出测试程序运行成功; 如果 BiscuitOS 因为找不到 PCIe 设备,那么请先参考下文安装设备:
3.17 添加一个支持 CXL 设备
BiscuitOS 已经支持 CXL 实践环境,开发者可以在 X86 架构下部署,部署逻辑如下:
BiscuitOS 默认提供两个 CXL.memory Type3 设备,作为 PMEM 使用,其大小为 128M. 更新 CXL 实践教程正在制作中,敬请期待.
3.18 添加一个 MINIXFS 数据盘
BiscuitOS 支持对 MINIXFS 文件系统的实践,BiscuitOS 可以通过一键部署一个 MINIXFS 文件系统的数据盘. 其部署逻辑如下:
BiscuitOS 系统启动之后,通过 mount 命令可以查看到系统将一个 MINIXFS 数据盘挂载到 /mnt/minix 目录下,并且磁盘里有一个 BiscuitOS.txt 的非空文件.
3.19 添加一个 EXT4 数据盘
BiscuitOS 支持对 EXT4 文件系统的实践,BiscuitOS 可以通过一键部署一个 EXT4 文件系统的数据盘. 其部署逻辑如下:
BiscuitOS 系统启动之后,通过 mount 命令可以查看到系统将一个 EXT4 数据盘挂载到 /mnt/ext4 目录下,并且磁盘里有一个 BiscuitOS.txt 的非空文件.
3.20 添加一个 EXT3 数据盘
BiscuitOS 支持对 EXT3 文件系统的实践,BiscuitOS 可以通过一键部署一个 EXT3 文件系统的数据盘. 其部署逻辑如下:
BiscuitOS 系统启动之后,通过 mount 命令可以查看到系统将一个 EXT3 数据盘挂载到 /mnt/ext2 目录下,并且磁盘里有一个 BiscuitOS.txt 的非空文件.
3.21 添加一个 TMPFS 文件系统
BiscuitOS 支持对 TMPFS 文件系统的实践,BiscuitOS 可以通过一键部署一个 TMPFS 文件系统的数据盘. 其部署逻辑如下:
BiscuitOS 系统启动之后,通过 mount 命令可以查看到系统将一个 TMPFS 文件系统挂载到 /mnt/tmpfs 目录下,并且文件系统里有一个 BiscuitOS.txt 的非空文件.