图片无法显示,请右键点击新窗口打开图片

目录


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 (适配中)

准备好一台开发机之后,开发者根据使用不同发行版需要提前安装开发工具,这些工具主要用于项目的下载和部署前期的准备,参考如下代码:

# Ubuntu/Debian
sudo apt-get update
sudo apt-get install git make figlet gawk flex bison
# CentOS
yum update
# ArchLinux

基础开发软件安装完毕之后,接下来从 Github/Gitee 上下载 BiscuitOS 项目源码,开发者为了加快下载速度可以使用 depth 参数,如果想看所有的代码提交,需要一定时间下载,参考如下代码:

git clone https://github.com/BiscuitOS/BiscuitOS.git --depth=1
or
git clone https://gitee.com/BiscuitOS_team/BiscuitOS.git --depth=1

  • 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 环境,也可以图形化的配置部署过程. 如果开发者是第一次部署, 那么需要执行如下命令完成开发工具的安装:

make defconfig
make install

基础环境安装完毕之后,那么接下来就是部署 Linux 开发环境了,开发者可以在 configs 目录下选择一个进行部署,configs 目录里面全部是某个架构指定 Linux 的部署配置,例如选择 linux-6.0-x86_64_defconfig, 名字中的 6.0 部署表示 Linux 源码版本是 Linux 6.0,名字中的 x86_64 字段指明部署的架构是 X86-64 架构,开发者使用如下命令:

make linux-6.0-x86_64_defconfig

命令执行完毕之后,BiscuitOS 项目将部署基于 X86-64 架构的 Linux 6.0 源码开发环境,如果开发者还想添加其他开源软件一同部署,那么可以直接使用命令开启图形化配置,与 Linux 内核的 Kbuild menuconfig 一致:

make 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 已经自动配置上图相关的配置,开发者可以根据自己的需要进行修改。修改完毕之后使用如下命令进行一键部署:

make

部署完毕之后,开发者会看到 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 部署应用程序,其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要部署的应用程序
make menuconfig

  [*] Package  --->
      [*] BiscuitOS Demo Code  --->
          [*] Application Demo Code on BiscuitOS  --->

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-Application-default/
# 部署源码
make download

应用程序开发环境的目录结构如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍,BiscuitOS-Application-default 目录下 “make download” 下载源码之后生成的,其中 main.c 是应用程序的源码, Makefile 是 main.c 编译文件,开发者可以根据自身需求修改编译过程,假如已经编译过源码,BiscuitOS-Application-default 是编译生成的可执行文件,最终在 BiscuitOS 上运行.

# 编译源码
make
# 安装应用程序
make install
# 更新 ROOTFS
make pack
# 运行 BiscuitOS
make run

当 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 部署内核模块,其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要部署的内核模块
make menuconfig

  [*] Package  --->
      [*] BiscuitOS Demo Code  --->
          [*] Module Demo Code on BiscuitOS  --->

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-modules-default/
# 部署源码
make download

内核模块开发环境的目录结构如上图,顶层的 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 上加载运行.

# 编译源码
make
# 安装源码
make install
# 打包 ROOTFS
make pack
# 运行 BiscuitOS
make run

当 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 程序,其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要部署的内核 INITCALL 程序
make menuconfig

  [*] Package  --->
      [*] BiscuitOS Demo Code  --->
          [*] Kernel Demo Code on BiscuitOS  --->

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-kernel-default/
# 部署源码
make download

内核 INITCALL 程序开发环境的目录结构如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍,KRunBiscuitOS.sh 做调试过滤信息使用,后面调试章节会详细介绍. BiscuitOS-kernel-default 目录下 “make download” 下载源码之后生成的,其中 main.c 是内核 INITCALL 程序的源码, Makefile 是 main.c 编译文件,Kconfig 是内核宏定义文件. 开发者可以修改 main.c 源文件里的 XXX_initcall 函数,以此确认程序运行的时机,最后在 BiscuitOS 上加载运行.

# 编译源码
make
# 安装源码
make install
# 打包 ROOTFS
make pack
# 运行 BiscuitOS
make run

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 进行部署和实践,其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要部署的内核 AnyWhere 程序
make menuconfig

  [*] Package  --->
      [*] BiscuitOS Demo Code  --->
          [*] Kernel Anywhere Demo Code on BiscuitOS  --->

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-kernel-any-default/
# 部署源码
make download

内核 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 上加载运行.

# 编译源码
make
# 安装源码
make install
# 打包 ROOTFS
make pack
# 运行 BiscuitOS
make run

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 进行部署和实践,其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要部署的字符设备模块
make menuconfig

  [*] Package  --->
      [*] BiscuitOS Demo Code  --->
          [*] Char-DD Demo Code on BiscuitOS  --->

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-Char-default/
# 部署源码
make download

字符设备开发环境的目录结构如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍. BiscuitOS-Char-default 目录下 “make download” 下载源码之后生成的,其中 main.c 是字符设备驱动的源码, app.c 是调用字符设备接口的应用程序,Makefile 是 main.c 编译文件,Kconfig 是内核宏定义文件, Makefile.host 是字符设备在主机上的编译脚本, RunBiscuitOS.sh 是实践案例运行的所有命令合集,最后在 BiscuitOS 上加载运行.

# 编译源码
make
# 安装源码
make install
# 打包 ROOTFS
make pack
# 运行 BiscuitOS
make run

当 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 进行部署和实践,其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要部署的 MISC 设备模块
make menuconfig

  [*] Package  --->
      [*] BiscuitOS Demo Code  --->
          [*] MISC-DD Demo Code on BiscuitOS  --->

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-MISC-default/
# 部署源码
make download

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 上加载运行.

# 编译源码
make
# 安装源码
make install
# 打包 ROOTFS
make pack
# 运行 BiscuitOS
make run

当 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 进行部署和实践,其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要部署的 Platform 设备模块
make menuconfig

  [*] Package  --->
      [*] BiscuitOS Demo Code  --->
          [*] Platform Device Driver Demo  --->

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-Platform-default/
# 部署源码
make download

Platform 设备开发环境的目录结构如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍. BiscuitOS-Platform-default 目录下 “make download” 下载源码之后生成的,其中 main.c 是 Platform 设备驱动的源码, Makefile 是 main.c 编译文件,Kconfig 是内核宏定义文件, Makefile.host 是 MISC 设备在主机上的编译脚本, RunBiscuitOS.sh 是实践案例运行的所有命令合集,最后在 BiscuitOS 上加载运行.

# 编译源码
make
# 安装源码
make install
# 打包 ROOTFS
make pack
# 运行 BiscuitOS
make run

当 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 进行部署和实践,其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要部署的 strace
make menuconfig

  [*] Package  --->
      [*] strace  --->

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/package/strace-5.0/
# 部署源码
make download
# 解压源码
make tar

第三方开源软件下载之后需,一般以压缩包形式存在,有的是直接从 git 仓库下载下来,此时需要使用 “make tar” 命令进行源码解压。解压之后如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍. strace-5.0.tar.xz 是源码压缩包,第一次部署时 BiscuitOS 会从网上进行下载,下载还之后放在 BiscuitOS 项目的 dl 目录下,因此在离线场景中,可以先将源码压缩包放在 dl 目录下; strace-5.0 目录是解压之后的源码目录,最后编译源码并在 BiscuitOS 上运行:

# 配置项目
make configure
# 编译源码
make
# 安装源码
make install
# 打包 ROOTFS
make pack
# 运行 BiscuitOS
make run

当 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 进行部署和实践,其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要部署的 libnuma
make menuconfig

  [*] Package  --->
      [*] NUMA Mechanism  --->
          [*] numctl tools and libnuma library  ---> 

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/package/numactl-libnuma-default/
# 部署源码
make download
# 解压源码
make tar

开源动态库下载之后需,一般以压缩包形式存在,有的是直接从 git 仓库下载下来,此时需要使用 “make tar” 命令进行源码解压。解压之后如上图,顶层的 Makefile 用于实现 BiscuitOS 编译控制,README.md 则是介绍编译控制命令介绍. 第一次部署时 BiscuitOS 会从网上进行下载,下载还之后放在 BiscuitOS 项目的 dl 目录下,因此在离线场景中,可以先将源码压缩包放在 dl 目录下; numactl-libnuma-default 目录是解压之后的源码目录,最后编译源码并在 BiscuitOS 上运行:

# 配置项目
make configure
# 编译源码
make
# 安装源码
make install
# 打包 ROOTFS
make pack
# 运行 BiscuitOS
make run

当 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 上部署内核开发工具集, 其部部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要部署的内核开发工具集
make menuconfig

  [*] Package  --->
      [*] BiscuitOS Demo Code  --->
          [*] Kernel Demo Code on BiscuitOS  --->

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-kernel-default/

内核开发工具集的目录结构如上图,顶层的 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 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          (4096) Memory Size(MiB)

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,可以看到系统物理内存已经变成了 4G.


3.2 修改 ROOTFS 大小

BiscuitOS 支持修改系统盘 ROOTFS 大小,其修改逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          (300) Rootfs Size(MiB)

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,使用 df 命令可以看到根目录 “/dev/root” 空间已经变成 467M(接近 500M),修改生效. 当开发者要注意,ROOTFS 越大,意味着打包 ROOTFS 所花费的时间就越多.


3.3 修改 CPU 数量

BiscuitOS 支持修改系使用的 CPU 数量,其修改逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          (2) CPU Number

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,查看 “/proc/cpuinfo” 节点确认 CPU 数量,上图可以看出 CPU 数量为 2,修改生效.


3.4 添加内核 CMDLINE

BiscuitOS 支持添加内核 CMDLINE,其修改逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          ()    CMDLINE on Kernel

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,查看 “/proc/cmdline” 节点可以看到内核正在使用的 CMDLINE,上图可以看出 “BiscuitOS=Ondemand” 字段,修改生效.


3.5 支持 NUMA 拓扑

BiscuitOS 支持添加 NUMA 拓扑结构,其修改逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          [*]   Support NUMA Topology

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,通过 “numactl” 命令可以查看系统 NUMA 拓扑结果,上图可以看出系统中存在两个 NUMA NODE,修改生效.


3.6 支持 CPU 特性直通

BiscuitOS 底层基于 QEMU 构建,因此在虚拟化场景或者某些特定场景下,需要直通 CPU 特性,其修改逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          [*] Support Host CPU Feature Passthrough

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,通过查看 /proc/cpuinfo 节点可以看到 CPU 硬件信息,上图可以看到 Host CPU 与 BiscuitOS 里 CPU 信息一致,修改生效.


3.7 支持 Broiler 自定义硬件

Broiler 项目是为 BiscuitOS 量身定制的硬件模拟工具,其模拟了多种 DMA、PCI、PCIe、MSIX 等硬件设备和场景,为实践特殊场景提供了可能,其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          [*] Support BiscuitOS Hardware Emulate

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/BiscuitOS-Broiler-default
# 运行 Broiler
make build

BiscuitOS 系统启动之后,自动加载 Broiler 继续运行,可以将 Broiler 理解为 BiscuitOS 系统里再启动一个 BiscuitOS,只是最终的 BiscuitOS 包含了很多特殊的硬件设备. Broiler 可以自定义很多硬件设备,甚至可以定义系统的物理地址空间布局,感兴趣的开发者可以参考:

Broiler Virtualization Technology


3.8 添加一个只包含 BAR 的 PCIe 设备

BiscuitOS 支持对 PCIe 的实践,可以通过一键部署一个只带 BAR 的 PCIe 设备. 其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          [*] BiscuitOS PCI/PCIe IO-BAR and MMIO-BAR

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS(非第一次运行)
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,可以使用 lspci 命令看到 1016:1413 设备为刚刚加载的 PCIe 设备, 可以看到 PCIe 设备包含了两个 BAR,BAR0 映射到 IO Space 空间,范围是: [0xC000, 0xD000), BAR1 映射到系统物理地址空间,其范围是: [0xFEBF1000m 0xFEBF2000), 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:

第一次部署
# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-QEMU-DEVICE-BAR-default/
# 下载源码
make download

通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-QEMU-DEVICE-BAR-default 拷贝到 QEMU 源码目录下,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
mkdir -p hw/BiscuitOS/
cp BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-QEMU-DEVICE-BAR-default/BiscuitOS-PCI-QEMU-DEVICE-BAR-default hw/BiscuitOS/ -rf
# 配置编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw

vi Makefile.objs
# Add context(已经存在就不需要配置)
devices-dirs-$(CONFIG_SOFTMMU) += BiscuitOS/

vi Kconfig
# Add context
source BiscuitOS/Kconfig

# 配置设备编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw/BiscuitOS

# Add context
vi Makefile.objs
common-obj-$(CONFIG_BISCUITOS_PCI_BAR) += BiscuitOS-PCI-QEMU-DEVICE-BAR-default/

vi Kconfig
# Add context
source BiscuitOS-PCI-QEMU-DEVICE-BAR-default/Kconfig

# 开启全局编译
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
vi default-configs/i386-softmmu.mak
# Add context
CONFIG_BISCUITOS_PCI_BAR=y

vi config-all-devices.mak
# Add context
CONFIG_BISCUITOS_PCI_BAR:=$(findstring y,$(CONFIG_BISCUITOS_PCI_BAR)y)

上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/
# 重编译 QEMU
./RunQEMU.sh -b

可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备 1016:1413, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/Broiler-pci-device-driver-default
# 下载源码
make download
# 实践
make build

BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,开发者可以直接看到实践案例的结果,提高执行的效率.


3.9 添加一个支持 INTX 中断的 PCIe 设备

BiscuitOS 支持对 PCIe 的实践,可以通过一键部署一个带 INTX 中断的 PCIe 设备. 其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          [*] BiscuitOS PCI/PCIe with INTX Interrupt

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS(非第一次运行)
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,可以使用 lspci 命令看到 1016:1991 设备为刚刚加载的 PCIe 设备, 可以看到 PCIe 设备包含了一个 BAR,BAR0 映射到 IO Space 空间,范围是: [0xC0C0, 0xC0E0), 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:

第一次部署
# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-QEMU-DEVICE-INTX-default/
# 下载源码
make download

通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-QEMU-DEVICE-INTX-default 拷贝到 QEMU 源码目录下,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
mkdir -p hw/BiscuitOS/
cp BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-QEMU-DEVICE-INTX-default/BiscuitOS-PCI-QEMU-DEVICE-INTX-default hw/BiscuitOS/ -rf
# 配置编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw

vi Makefile.objs
# Add context(已经存在就不需要配置)
devices-dirs-$(CONFIG_SOFTMMU) += BiscuitOS/

vi Kconfig
# Add context(已经存在就不需要修改)
source BiscuitOS/Kconfig

# 配置设备编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw/BiscuitOS

# Add context
vi Makefile.objs
common-obj-$(CONFIG_BISCUITOS_PCI_INTX) += BiscuitOS-PCI-QEMU-DEVICE-INTX-default/

vi Kconfig
# Add context
source BiscuitOS-PCI-QEMU-DEVICE-INTX-default/Kconfig

# 开启全局编译
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
vi default-configs/i386-softmmu.mak
# Add context
CONFIG_BISCUITOS_PCI_INTX=y

vi config-all-devices.mak
# Add context
CONFIG_BISCUITOS_PCI_INTX:=$(findstring y,$(CONFIG_BISCUITOS_PCI_INTX)y)

上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/
# 重编译 QEMU
./RunQEMU.sh -b

可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备 1016:1991, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/Broiler-pci-intx-interrupt-default
# 下载源码
make download
# 实践
make build

BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,并且收到 PCIe 设备的 INTX 中断 IRQ11. 开发者可以直接看到实践案例的结果,提高执行的效率.


3.10 添加一个支持 MSI 中断的 PCIe 设备

BiscuitOS 支持对 PCIe 的实践,可以通过一键部署一个带 MSI 中断的 PCIe 设备. 其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          [*] BiscuitOS PCI/PCIe with MSI Interrupt

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS(非第一次运行)
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,可以使用 lspci 命令看到 1001:1991 设备为刚刚加载的 PCIe 设备, 可以看到 PCIe 设备包含了一个 BAR,BAR0 映射到 IO Space 空间,范围是: [0xC0C0, 0xC0E0), 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:

第一次部署
# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-QEMU-DEVICE-INTX-default/
# 下载源码
make download

通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-QEMU-DEVICE-MSI-default 拷贝到 QEMU 源码目录下,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
mkdir -p hw/BiscuitOS/
cp BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-QEMU-DEVICE-MSI-default/BiscuitOS-PCI-QEMU-DEVICE-MSI-default hw/BiscuitOS/ -rf
# 配置编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw

vi Makefile.objs
# Add context(已经存在就不需要配置)
devices-dirs-$(CONFIG_SOFTMMU) += BiscuitOS/

vi Kconfig
# Add context(已经存在就不需要修改)
source BiscuitOS/Kconfig

# 配置设备编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw/BiscuitOS

# Add context
vi Makefile.objs
common-obj-$(CONFIG_BISCUITOS_PCI_MSI) += BiscuitOS-PCI-QEMU-DEVICE-MSI-default/

vi Kconfig
# Add context
source BiscuitOS-PCI-QEMU-DEVICE-MSI-default/Kconfig

# 开启全局编译
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
vi default-configs/i386-softmmu.mak
# Add context
CONFIG_BISCUITOS_PCI_MSI=y

vi config-all-devices.mak
# Add context
CONFIG_BISCUITOS_PCI_MSI:=$(findstring y,$(CONFIG_BISCUITOS_PCI_MSI)y)

上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/
# 重编译 QEMU
./RunQEMU.sh -b

可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备 1001:1991, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/Broiler-pci-msi-interrupt-default
# 下载源码
make download
# 实践
make build

BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,并且收到 PCIe 设备的 MSI 中断 IRQ26. 开发者可以直接看到实践案例的结果,提高执行的效率.


3.11 添加一个支持 MSIX 中断的 PCIe 设备

BiscuitOS 支持对 PCIe 的实践,可以通过一键部署一个带 MSIX 中断的 PCIe 设备. 其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          [*] BiscuitOS PCI/PCIe with MSIX Interrupt

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS(非第一次运行)
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,可以使用 lspci 命令看到 1002:1991 设备为刚刚加载的 PCIe 设备, 可以看到 PCIe 设备包含了一个 BAR,BAR0 映射到 IO Space 空间,范围是: [0xC0C0, 0xC0E0), 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:

第一次部署
# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-QEMU-DEVICE-MSIX-default/
# 下载源码
make download

通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-QEMU-DEVICE-MSIX-default 拷贝到 QEMU 源码目录下,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
mkdir -p hw/BiscuitOS/
cp BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-QEMU-DEVICE-MSIX-default/BiscuitOS-PCI-QEMU-DEVICE-MSIX-default hw/BiscuitOS/ -rf
# 配置编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw

vi Makefile.objs
# Add context(已经存在就不需要配置)
devices-dirs-$(CONFIG_SOFTMMU) += BiscuitOS/

vi Kconfig
# Add context(已经存在就不需要修改)
source BiscuitOS/Kconfig

# 配置设备编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw/BiscuitOS

# Add context
vi Makefile.objs
common-obj-$(CONFIG_BISCUITOS_PCI_MSIX) += BiscuitOS-PCI-QEMU-DEVICE-MSIX-default/

vi Kconfig
# Add context
source BiscuitOS-PCI-QEMU-DEVICE-MSIX-default/Kconfig

# 开启全局编译
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
vi default-configs/i386-softmmu.mak
# Add context
CONFIG_BISCUITOS_PCI_MSIX=y

vi config-all-devices.mak
# Add context
CONFIG_BISCUITOS_PCI_MSIX:=$(findstring y,$(CONFIG_BISCUITOS_PCI_MSIX)y)

上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/
# 重编译 QEMU
./RunQEMU.sh -b

可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备 1002:1991, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/Broiler-pci-msix-interrupt-default
# 下载源码
make download
# 实践
make build

BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,并且收到 PCIe 设备的 MSI 中断 IRQ26. 开发者可以直接看到实践案例的结果,提高执行的效率.


3.12 添加一个支持 INTX/DMA 中断的 PCIe 设备

BiscuitOS 支持对 PCIe 的实践,可以通过一键部署一个带 DMA/INTX 中断的 PCIe 设备. 其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          [*] BiscuitOS PCI/PCIe DMA with INTX Interrupt

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS(非第一次运行)
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,可以使用 lspci 命令看到 0309:1989 设备为刚刚加载的 PCIe 设备, 可以看到 PCIe 设备包含了一个 BAR,BAR0 映射到 IO Space 空间,范围是: [0xC0C0, 0xC0E0), 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:

第一次部署
# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-DMA-QEMU-DEVICE-INTX-default/
# 下载源码
make download

通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-DMA-QEMU-DEVICE-INTX-default 拷贝到 QEMU 源码目录下,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
mkdir -p hw/BiscuitOS/
cp BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-DMA-QEMU-DEVICE-INTX-default/BiscuitOS-PCI-DMA-QEMU-DEVICE-INTX-default hw/BiscuitOS/ -rf
# 配置编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw

vi Makefile.objs
# Add context(已经存在就不需要配置)
devices-dirs-$(CONFIG_SOFTMMU) += BiscuitOS/

vi Kconfig
# Add context(已经存在就不需要修改)
source BiscuitOS/Kconfig

# 配置设备编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw/BiscuitOS

# Add context
vi Makefile.objs
common-obj-$(CONFIG_BISCUITOS_PCI_DMA_INTX) += BiscuitOS-PCI-DMA-QEMU-DEVICE-INTX-default/

vi Kconfig
# Add context
source BiscuitOS-PCI-DMA-QEMU-DEVICE-INTX-default/Kconfig

# 开启全局编译
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
vi default-configs/i386-softmmu.mak
# Add context
CONFIG_BISCUITOS_PCI_DMA_INTX=y

vi config-all-devices.mak
# Add context
CONFIG_BISCUITOS_PCI_DMA_INTX:=$(findstring y,$(CONFIG_BISCUITOS_PCI_DMA_INTX)y)

上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/
# 重编译 QEMU
./RunQEMU.sh -b

可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备 0309:1989, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/Broiler-dma-intx-default
# 下载源码
make download
# 实践
make build

BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,并且收到 PCIe 设备的 INTX 中断 IRQ11, 最后通过 DMA 读取到字符串. 开发者可以直接看到实践案例的结果,提高执行的效率.


3.13 添加一个支持 MSI 中断的 PCIe 设备

BiscuitOS 支持对 PCIe 的实践,可以通过一键部署一个带 DMA/MSI 中断的 PCIe 设备. 其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          [*] BiscuitOS PCI/PCIe DMA with MSI Interrupt

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS(非第一次运行)
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,可以使用 lspci 命令看到 1024:1991 设备为刚刚加载的 PCIe 设备, 可以看到 PCIe 设备包含了一个 BAR,BAR0 映射到 IO Space 空间,范围是: [0xC0C0, 0xC0E0), 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:

第一次部署
# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-DMA-QEMU-DEVICE-INTX-default/
# 下载源码
make download

通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-DMA-QEMU-DEVICE-MSI-default 拷贝到 QEMU 源码目录下,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
mkdir -p hw/BiscuitOS/
cp BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-DMA-QEMU-DEVICE-MSI-default/BiscuitOS-PCI-DMA-QEMU-DEVICE-MSI-default hw/BiscuitOS/ -rf
# 配置编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw

vi Makefile.objs
# Add context(已经存在就不需要配置)
devices-dirs-$(CONFIG_SOFTMMU) += BiscuitOS/

vi Kconfig
# Add context(已经存在就不需要修改)
source BiscuitOS/Kconfig

# 配置设备编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw/BiscuitOS

# Add context
vi Makefile.objs
common-obj-$(CONFIG_BISCUITOS_PCI_DMA-MSI) += BiscuitOS-PCI-DMA-QEMU-DEVICE-MSI-default/

vi Kconfig
# Add context
source BiscuitOS-PCI-DMA-QEMU-DEVICE-MSI-default/Kconfig

# 开启全局编译
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
vi default-configs/i386-softmmu.mak
# Add context
CONFIG_BISCUITOS_PCI_DMA_MSI=y

vi config-all-devices.mak
# Add context
CONFIG_BISCUITOS_PCI_DMA_MSI:=$(findstring y,$(CONFIG_BISCUITOS_PCI_DMA_MSI)y)

上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/
# 重编译 QEMU
./RunQEMU.sh -b

可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备 1024:1991, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/Broiler-dma-msi-default
# 下载源码
make download
# 实践
make build

BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,并且通过 DMA 搬运从设备获得字符串. 开发者可以直接看到实践案例的结果,提高执行的效率.


3.14 添加一个支持 DMA/MSIX 中断的 PCIe 设备

BiscuitOS 支持对 PCIe 的实践,可以通过一键部署一个带 DMA/MSIX 中断的 PCIe 设备. 其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          [*] BiscuitOS PCI/PCIe DMA with MSIX Interrupt

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS(非第一次运行)
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,可以使用 lspci 命令看到 1002:1991 设备为刚刚加载的 PCIe 设备, 可以看到 PCIe 设备包含了一个 BAR,BAR0 映射到 IO Space 空间,范围是: [0xC0C0, 0xC0E0), 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:

第一次部署
# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-DMA-QEMU-DEVICE-MSIX-default/
# 下载源码
make download

通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-DMA-QEMU-DEVICE-MSIX-default 拷贝到 QEMU 源码目录下,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
mkdir -p hw/BiscuitOS/
cp BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-DMA-QEMU-DEVICE-MSIX-default/BiscuitOS-PCI-DMA-QEMU-DEVICE-MSIX-default hw/BiscuitOS/ -rf
# 配置编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw

vi Makefile.objs
# Add context(已经存在就不需要配置)
devices-dirs-$(CONFIG_SOFTMMU) += BiscuitOS/

vi Kconfig
# Add context(已经存在就不需要修改)
source BiscuitOS/Kconfig

# 配置设备编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw/BiscuitOS

# Add context
vi Makefile.objs
common-obj-$(CONFIG_BISCUITOS_PCI_DMA_MSIX) += BiscuitOS-PCI-DMA-QEMU-DEVICE-MSIX-default/

vi Kconfig
# Add context
source BiscuitOS-PCI-DMA-QEMU-DEVICE-MSIX-default/Kconfig

# 开启全局编译
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
vi default-configs/i386-softmmu.mak
# Add context
CONFIG_BISCUITOS_PCI_DMA_MSIX=y

vi config-all-devices.mak
# Add context
CONFIG_BISCUITOS_PCI_DMA_MSIX:=$(findstring y,$(CONFIG_BISCUITOS_PCI_DMA_MSIX)y)

上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/
# 重编译 QEMU
./RunQEMU.sh -b

可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备 1026:1991, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/Broiler-dma-msix-default
# 下载源码
make download
# 实践
make build

BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,并从设备 DMA 搬运内容进行了打印. 开发者可以直接看到实践案例的结果,提高执行的效率.


3.15 添加一个支持 DMA-BUF 的设备

BiscuitOS 支持对 DMA-BUF 的实践,DMA-BUF 主要解决多个外设之间共享内存的问题,可以通过一键部署多个设备实现 DMA-BUF 场景. 其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

      [*] DIY BiscuitOS/Broiler Hardware --->
          [*] BiscuitOS PCI/PCIe DMA-BUF

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS(非第一次运行)
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,可以使用 lspci 命令看到: EXPORTER 1018:1991, IMPORTA: 1019:1991, IMPORTB: 101A:1991, 至此 PCIe 设备添加成功; 如果没有找到,那么说明 PCIe 设备还没有在 QEMU 里部署,因此需要进行部署,参考如下步骤:

第一次部署
# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-DMA-BUF-QEMU-DEVICE-default/
# 下载源码
make download

通过上面命令可以获得 PCIe 模拟设备的源码,接下来将下载获得源码目录 BiscuitOS-PCI-DMA-BUF-QEMU-DEVICE-default 拷贝到 QEMU 源码目录下,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
mkdir -p hw/BiscuitOS/
cp BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-PCI-DMA-BUF-QEMU-DEVICE-default/BiscuitOS-PCI-DMA-BUF-QEMU-DEVICE-default hw/BiscuitOS/ -rf
# 配置编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw

vi Makefile.objs
# Add context(已经存在就不需要配置)
devices-dirs-$(CONFIG_SOFTMMU) += BiscuitOS/

vi Kconfig
# Add context(已经存在就不需要修改)
source BiscuitOS/Kconfig

# 配置设备编译逻辑
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/hw/BiscuitOS

# Add context
vi Makefile.objs
common-obj-$(CONFIG_BISCUITOS_PCI_DMA_BUF) += BiscuitOS-PCI-DMA-BUF-QEMU-DEVICE-default/

vi Kconfig
# Add context
source BiscuitOS-PCI-DMA-BUF-QEMU-DEVICE-default/Kconfig

# 开启全局编译
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/qemu-system/
vi default-configs/i386-softmmu.mak
# Add context
CONFIG_BISCUITOS_PCI_DMA_BUF=y

vi config-all-devices.mak
# Add context
CONFIG_BISCUITOS_PCI_DMA_BUF:=$(findstring y,$(CONFIG_BISCUITOS_PCI_DMA_BUF)y)

上述配置完毕之后,需要重新编译 QEMU,可以参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/qemu-system/
# 重编译 QEMU
./RunQEMU.sh -b

可以看到 BiscuitOS 运行之后,使用 lspci 工具看到 PCIe 对应的设备: EXPORTER 1018:1991, IMPORTA: 1019:1991, IMPORTB: 101A:1991, 说明 PCIe 模拟设备添加成功,接下来是部署实践案例,参考如下命令:

# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-DMA-DMABUF-with-QEMU-Device-default
# 下载源码
make download
# 实践
make build

BiscuitOS 运行之后,直接运行 RunBiscuitOS.sh 实践脚本,可以运行实践所需的所有命令,从实践可以看出系统正常访问 PCIe 设备,并可以看到 Exportor 生产的数据被 Importor 消费了. 开发者可以直接看到实践案例的结果,提高执行的效率.


3.16 添加一个支持 IOMMU 的设备

BiscuitOS 支持对 IOMMU 的实践,IOMMU 要解决的其中一个问题外设可以映射不连续的物理内存. BiscuitOS 可以通过一键部署对 IOMMU 支持. 其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

 [*] DIY BiscuitOS/Broiler Hardware --->
     [*] Intel Q35
     [*]    vIOMMU   
     [*] BiscuitOS PCI/PCIe DMA with MSIX Interrupt
 [*] Package
     [*] IOMMU: Input/Output Memory Management Unit  --->
         [*] IOMMU: PCI DMA MSIX with IOMMU  --->

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/package/BiscuitOS-IOMMU-PCI-DMA-MSIX-default
# 下载源码
make downlaod
# 编译并运行源码
make build

BiscuitOS 系统启动之后,从 dmesg 中查看 IOMMU 相关的初始化信息,另外直接运行 RunBiscuitOS.sh 可以运行基于 IOMMU 的 DMA 搬运,上图可以看出测试程序运行成功; 如果 BiscuitOS 因为找不到 PCIe 设备,那么请先参考下文安装设备:

添加一个支持 DMA/MSIX 中断的 PCIe 设备


3.17 添加一个支持 CXL 设备

BiscuitOS 已经支持 CXL 实践环境,开发者可以在 X86 架构下部署,部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

  [*] DIY BiscuitOS/Broiler Hardware  --->
      [*] Support Host CPU Feature Passthrough  --->
      -*-   Intel Q35
      [*]   CXL: Compute Express Link


make
# 源码目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 在 BiscuitOS 中实践
./RunBiscuitOS.sh

BiscuitOS 默认提供两个 CXL.memory Type3 设备,作为 PMEM 使用,其大小为 128M. 更新 CXL 实践教程正在制作中,敬请期待.


3.18 添加一个 MINIXFS 数据盘

BiscuitOS 支持对 MINIXFS 文件系统的实践,BiscuitOS 可以通过一键部署一个 MINIXFS 文件系统的数据盘. 其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

 [*] DIY BiscuitOS/Broiler Hardware --->
     [*] Virtio-BLK: MINIX Filesystem Disk

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,通过 mount 命令可以查看到系统将一个 MINIXFS 数据盘挂载到 /mnt/minix 目录下,并且磁盘里有一个 BiscuitOS.txt 的非空文件.


3.19 添加一个 EXT4 数据盘

BiscuitOS 支持对 EXT4 文件系统的实践,BiscuitOS 可以通过一键部署一个 EXT4 文件系统的数据盘. 其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

 [*] DIY BiscuitOS/Broiler Hardware --->
     [*] Virtio-BLK: EXT4 Filesystem Disk

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,通过 mount 命令可以查看到系统将一个 EXT4 数据盘挂载到 /mnt/ext4 目录下,并且磁盘里有一个 BiscuitOS.txt 的非空文件.


3.20 添加一个 EXT3 数据盘

BiscuitOS 支持对 EXT3 文件系统的实践,BiscuitOS 可以通过一键部署一个 EXT3 文件系统的数据盘. 其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

 [*] DIY BiscuitOS/Broiler Hardware --->
     [*] Virtio-BLK: EXT3 Filesystem Disk

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,通过 mount 命令可以查看到系统将一个 EXT3 数据盘挂载到 /mnt/ext2 目录下,并且磁盘里有一个 BiscuitOS.txt 的非空文件.


3.21 添加一个 TMPFS 文件系统

BiscuitOS 支持对 TMPFS 文件系统的实践,BiscuitOS 可以通过一键部署一个 TMPFS 文件系统的数据盘. 其部署逻辑如下:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.0 X86 为例
make linux-6.0-x86_64_defconfig
# 通过 Kbuild 选择需要修改的项目
make menuconfig

 [*] DIY BiscuitOS/Broiler Hardware --->
     [*] Pseudo Filesystem: TMPFS

# 配置完毕保存,然后进行部署
make

# 部署完毕之后,切换到开发环境所在的目录
cd BiscuitOS/output/linux-6.0-x86_64/
# 运行 BiscuitOS
./RunBiscuitOS.sh

BiscuitOS 系统启动之后,通过 mount 命令可以查看到系统将一个 TMPFS 文件系统挂载到 /mnt/tmpfs 目录下,并且文件系统里有一个 BiscuitOS.txt 的非空文件.