一、前言:
相信很多人都有使用模拟器的需求,因为并不是所有的场景都能用虚拟机代劳,如果你需要对程序精心的调试,实时查看内存与寄存器信息、研究指令集的工作原理,那么模拟器就是一种非常重要的工具。常见的模拟器有很多,最出名的就是Qemu,它既可以作为模拟器又可以作为虚拟机使用,并且对大多数CPU指令集架构提供支持,且有多种工作模式,支持kvm加速、gdb调试等等功能,可以说对于操作系统内核开发、嵌入式开发、指令集设计等都有着非常重要的作用。但是我今天不讲Qemu而是另一个开源的x86模拟器 --- bochs(读音同:box [bɒks]).对于内核开发者来说,这也是一个非常重要的工具,它可以提供比Qemu+gdb更加精细、精准的调试,可以查看更多的信息,对于内核开发初学者来说是一个强悍的工具,更重要的是它是开源的,并且现在还在更新。
bochs当前信息
bochs官网
bochs官方文档
bochs下载地址
bochs百度百科
bochs作为一个开源工具,它本身是可以使用GNU/linux自带的包管理器安装的,但直接使用包管理器安装的bochs并不具备调试功能,如果想使用bochs来调试自己的内核,请务必下载它的源代码并自己配置和编译。
至于为什么我会想起来写bochs的文档,那正是因为bochs在今年(2024)三月份发布了其最新版本bochs-2.8,我就想开源开发者这么努力、坚持不懈做出更好、更先进、支持更多CPU和指令集的模拟器,那么我是不是也该为社区做一点什么呢?bochs的英文文档可以说是已经非常详细了,但是它的中文文档好像就比较少,只有一些自己配置bochs的资料,对于全面使用bochs模拟器来调试内核来说还是不太够用,那么希望大家看了这篇文章就可以配置出适合自己的bochs模拟器,并用它来调试和学习x86架构和操作系统内核。
最新版新增了几块现代CPU,有了这些新CPU,就可以在模拟器里为自己的内核开发出更多的基础功能,大家不要着急,我会在后面的章节告诉大家怎么把这些CPU给使用起来,让自己的操作系统内核跑在如图所示的先进的CPU上面。祝大家内核学习顺利吧。
二、Bochs简介
1、什么是Bochs
Bochs是一个完整模拟Intel x86指令集的计算机程序。它包括对Intel x86CPU、常见IO设备和自定义BIOS的仿真,除了IntelCPU之外还有AMD处理器的支持。Bochs拥有标准PC外设的设备模型:鼠标、键盘、VGA卡/显示器、磁盘、定时器芯片、网卡等。
Bochs最早由Kevin Lawton大佬于1994年开始编写,2000年3月,Bochs以LGPL协议开源出来。
它一开始使用svn集中式版本管理工具,现在已经改成了Git分布式版本管理来管理项目。
LGPL协议:This library is free software; you can redistribute it and/ormodify it under the terms of the GNU Lesser General PublicLicense as published by the Free Software Foundation; eitherversion 2 of the License, or (at your option) any later version.This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNULesser General Public License for more details.You should have received a copy of the GNU Lesser General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2、Bochs能在哪些机器上运行
Bochs使用C++编程语言编写,由于C++具有跨平台性,因此Bochs可以在x86,PPC,Alpha,Sun,MIPS等指令集的CPU上面运行。Bochs是一个单纯的模拟器、它不是虚拟机,它的指令集的实现并不依赖于宿主机本身拥有的指令集,也就是不使用VMX等虚拟化指令集的支持。Bochs支持x86的高度仿真,也就是可以把它当成一台物理机器,拥有自己的BIOS。
bochs实际上提供了源码包、exe文件和rpm包,其中最重要的就是源代码。有了源代码,Bochs可以拿来跑在很多机器上,只是可能需要自己去编译和构建。
3、Bochs模拟器适合哪些人使用
实际上Bochs完全可以拿来当成一个“虚拟机”,比如在没有Windows生态的机器上跑Windows操作系统。不过我是站在内核开发者的角度来看,更多把Bochs作为一个能够模拟真实PC环境的仿真工具。实际上Bochs在为indows、Linux、MacOS都可以跑,由于我没有其中一些设备,因此我就在GNU/Linux上面使用Bochs作为例子。
三、准备使用Bochs
1、下载Bochs的源代码
Bochs模拟器有很多版本,从最开始的1.0版本到现在最新的2.8版本,大家需要选择一个合适的版本,不同版本有不同的特点,使用的配置文件的语法也不尽相同,如果大家知道自己需要哪一个版本就最好,如果大家不知道该选择哪一个版本那么我推荐大家使用Bochs-2.8也就是最新的版本,我也是按照这个版本的文档写成的中文文档。
点进Bochs2.8这个目录,可以看到提供了很多不同的包,那么我们这里选择下载源码包,名称中带有src的就是源码包。.zip源码包带有msvc字样,应该是给Windows用的。我主要在Linux上写内核,因此会选择bochs-2.8.tar.gz.
2、解压并观察源代码
tar -xvf bochs-2.8.tar.gz
解压后会在tar包所在目录产生一个新目录bochs-2.8
我们不要急着就开始配置和编译,而是要先观察。
文件/目录 | 作用 |
configure | 非常重要的shell脚本,配置的时候执行它 |
Makefile.in | 根据configure脚本的配置 生成最终的Makefile文件 |
install-sh | 用于在安装过程中复制文件 |
main.cc | Bochs的主程序入口点 |
bios目录 | 包含Bochs使用的BIOS文件 |
gui目录 | Bochs支持图形界面调试(不过我更喜欢字符界面调试) |
我们在最终执行make install之前实际上要稍微修改一些文件才能编译通过,否则可能会出现错误,因此需要简单了解一下目录里面的构成。
3、配置Bochs
这一步可以说是最重要的,我们怎么配置Bochs,那么最终构建出来的Bochs就会具有什么样的能力;或者说关闭一些配置,那么Bochs就会失去什么样的能力。
我们在执行make install 之前执行./configure,但不是直接这么执行就好,而是要自己配置。
比如./configure --with-x11 ....等一系列配置
平台相关的配置
Platform | GUI | 说明 |
Win32/MinGW | --with-win32 | Windows平台带上这个参数 |
MacOS/Darwin | --with-carbon | Mac平台带上这个参数 |
MacOS9 | --with-macos | 这应该比较老了 |
AmigaOS | --with-amigaos | 我不了解这个系统 |
带有x显示服务器的Linux | --with-x11 | Linux上用这个参数 |
虽然说是需要带有x显示服务器的Linux用--with-x11,但实际上只要是Linux就用这个参数就好了,Bochs是可以跑在Xwayland上面的。
Bochs使用的图形库
由于Bochs是跑在操作系统上的,因此需要调用图形库才能使用。
显示库选项 | 作用 |
--with-x11 | Linux上用这个 |
--with-win32 | Win32原生GUI |
--with-carbon | 使用Carbon GUI |
--with-sdl | 启用对SDL 1.2.x GUI接口的支持 |
--with-sdl2 | 启用对SDL 2.x GUI接口的支持 |
--with-term | 需要curses库 |
--with-wx | 启用对wxWidgets配置和显示接口的支持 |
--with-nogui | 你不关心视频输出/单纯调试 |
--with-all-libs | 自动检测系统上安装的库(我没试过) |
我启动了三个选项
--with-x11 --with-wx --with-sdl2
大家可以参考我的做法
Bochs通用配置
这会是一个大的表格,如果大家没有耐心看了,那么可以直接参考我的做法
通用选项 | 默认情况 | 说明 |
--enable-plugins | 关 | 启用插件支持 |
--enable-debugger | 关 | Bochs内置调试器,默认关闭因此使用包管理器安装的Bochs不带调试功能 |
--enable-debugger-gui | 开(如果debugger开) | 有图形界面的调试器 |
--enable-readline | - | 提供命令行编辑和历史记录功能 |
--enable-gdb-stub | 关 | 使用gdb调试,它与--enable-debugger不兼容,并且gdb调试和smp也不兼容 |
--enable-docbook | - | 如果系统安装了docbook2html则默认开启 |
--enable-instrumentation=directory | 关 | 仪器支持 |
--enable-xpm | 开 | XMP |
--enable-show-ips | 开 | 启用测量IPS(每秒指令数)的日志记录功能 |
--enable-logging | 开 | 运行时记录日志 |
--enable-cpp | 关 | 将所有.cc文件重命名为.cpp |
--enable-idle-hack | 关 | 保持Bochs响应性(Bochs不占用过量的系统资源) |
--enable-assert-checks | - | BX_ASSERT事件在断言失败时会导致panic |
我的做法:除了--enable-docbook,全开
CPU与内存配置
配置参数 | 默认情况 | 说明 |
--enable-cpu-level={3,4,5,6} | 6 | 386/486/586/686及以上(你选6就好) |
--enable-smp | 关 | 对称多处理器支持 |
--enable-fpu | 开 | 浮点运算单元 |
--enable-3dnow | 关 | AMD的指令集 |
--enable-vmx | 关 | 支持Intel虚拟化扩展(VMX) |
--enable-svm | 关 | 支持AMD SVM(安全虚拟机)扩展模拟 |
--enable-avx | 关 | 支持AVX指令集 |
--enable-x86-debugger | 关 | 支持x86调试器 |
--enable-monitor-mwait | 关 | 支持MONITOR/MWAIT指令 |
--enable-alignment-check | - | 如果CPU级别大于4则开启(支持CPU中的对齐检查和#AC异常) |
--enable-configurable-msrs | 关 | 支持用户配置模拟的MSR |
--enable-long-phy-address | 关 | 支持大于32位的客户物理地址 |
--enable-a20-pin | 开 | 支持A20引脚 |
--enable-large-ramfile | 开 | 支持大于主机支持的客户内存 |
--enable-repeat-speedups | 关 | 启用对重复I/O和内存复制加速的支持 |
--enable-fast-function-calls | 关 | 启用对快速函数调用的支持 |
--enable-handlers-chaining | 关 | 启用对处理程序链优化的支持 |
--enable-all-optimizations | 关 | 开启所有开发者认为安全使用的速度优化选项:--enable-repeat-speedups 、--enable-fast-function-calls 、--enable-handlers-chaining |
我的做法:全部打开
对设备的模拟支持
配置选项 | 默认情况 | 说明 |
--enable-cdrom | 开 | 启用对真实CD-ROM/DVD驱动器的使用 |
--enable-sb16 | 关 | 启用Sound Blaster模拟,可用的低级声音接口会自动检测。 |
--enable-es1370 | 关 | 启用ES1370声音模拟 |
--enable-gameport | 关 | 启用标准PC游戏端口 |
--enable-ne2000 | 关 | 启用NE2000网络卡支持 |
--enable-pnic | 关 | 启用PCI伪NIC(网络卡)支持 |
--enable-e1000 | 关 | 启用Intel(R) 82540EM千兆以太网适配器支持 |
--enable-clgd54xx | 关 | 启用Cirrus Logic GD54xx(CL-GD5430 ISA或CL-GD5446 PCI)视频卡支持 |
--enable-voodoo | 关 | 启用实验性的3dfx Voodoo Graphics模拟。Voodoo1已知可以工作,Voodoo2支持尚未完成,但几乎可用 |
--enable-iodebug | 跟随debugger | Dave Poirier编写了一个使用I/O端口的实验性调试器接口,使得在客户操作系统中运行的软件可以访问调试器的功能 |
--enable-pci | 开 | 启用有限的i440FX / i430FX / i440BX PCI支持 |
--enable-pcidev | 关 | 启用PCI主机设备映射支持 |
--enable-usb | 关 | 启用i440FX / i440BX PCI USB支持(UHCI) |
--enable-usb-ohci | 关 | 启用USB OHCI支持,提供带有2端口根集线器的主控制器 |
--enable-usb-ehci | 关 | 启用USB EHCI支持,提供带有6端口根集线器的主控制器 |
--enable-usb-xhci | 关 | 启用USB xHCI支持,提供带有4端口根集线器的主控制器 |
--enable-raw-serial | 关 | 启用对串行端口模拟的支持,以访问宿主的串行端口 |
我的做法:--enable-voodoo --enable-iodebug可以打开
其他配置你可以根据自己的情况自行配置,比如你想写USB驱动,那么就可以打开--enable-usb等
总结configure
相比大家对官方文档里的这些配置参数有了一定的了解,可以看到,参数真的非常的多,如果大家不知道哪些是自己必备的,那么你可以尽可能多的选择一些参数,编译出来你不使用也是可以的。但是如果你参数加少了,那么你就得重新编译了,这样得不偿失。
这里我提供我自己的configre
./configure --with-x11 --with-wx --with-sdl2 --enable-plugins --enable-debugger --enable-debugger-gui --enable-readline --enable-xpm --enable-show-ips --enable-logging --enable-assert-checks --enable-cpp --enable-idle-hack --enable-cpu-level=6 --enable-smp --enable-fpu --enable-3dnow --enable-x86-64 --enable-vmx --enable-svm --enable-avx --enable-x86-debugger --enable-monitor-mwait --enable-alignment-check --enable-configurable-msrs --enable-long-phy-address --enable-a20-pin --enable-large-ramfile --enable-repeat-speedups --enable-fast-function-calls --enable-handlers-chaining --enable-all-optimizations --enable-cdrom --enable-sb16 --enable-es1370 --enable-gameport --enable-ne2000 --enable-pnic --enable-e1000 --enable-clgd54xx --enable-voodoo --enable-iodebug --enable-pci --enable-pcidev --enable-usb --enable-usb-ohci --enable-usb-ehci --enable-usb-xhci --enable-raw-serial --enable-vmx=2 --prefix=/home/april_zhao/bochs
大家可以看到我还添加了一个参数--prefix=directory
这里最重要的一点我在前面的表格里已经提到了:--enable-gdb-stub这个参数和--enable-debugger是不能共存的,也就是你要么使用bochs自带的调试工具,要么使用gdb远程调试,不可兼得。并且gdb调试是不能够开启smp的,也就是--enable-gdb-stub和--enable-smp不能共存。
因此我在这里推荐,尽量使用bochs自带的调试工具吧,除非你的内核不需要开启smp或者你不需要多核处理器的支持。
这个参数就是给Bochs安一个家,否则会放置到默认的FHS位置,由于我在调试内核的时候可能会使用不同版本和编译参数的Bochs,因此我不会去使用系统全局的Bochs而是我项目本地的Bochs,因此放置到一个我自己创建的目录里。
做好这一些配置之后,大家千万不要忙着直接就make install,因为这么多很有可能会出错的。
make前的准备
cp misc/bximage.cpp misc/bximage.cc
cp iodev/hdimage/hdimage.cpp iodev/hdimage/hdimage.cc
cp iodev/hdimage/vmware3.cpp iodev/hdimage/vmware3.cc
cp iodev/hdimage/vmware4.cpp iodev/hdimage/vmware4.cc
cp iodev/hdimage/vpc.cpp iodev/hdimage/vpc.cc
cp iodev/hdimage/vbox.cpp iodev/hdimage/vbox.cc
cp misc/bxhub.cpp misc/bxhub.cc
cp iodev/network/netutil.cpp iodev/network/netutil.cc
在我的配置中,我就需要做一些cp操作,修改一些c++程序的文件名,否则会导致报错,大家可以跟着这么做,然后再执行make install ,假如这么做了之后还是报错了,那么大家有可能需要更多的cp操作,同样是把.cpp文件替换成.cc文件就好。在编译过程中还会出现各种各样的错误,它们很有可能是因为你的系统缺少了某些库或者包,这就需要大家根据报错日志自行安装这些缺少的库,使用包管理器安装就好了。安装好之后再执行make install,如果还是提示同样的错误,那么你可以重新执行./configure然后再make install.
make install执行成功之后,在你的--prefix指定的目录里会出现三个新目录:bin lib share
bin目录最关键,它里面保存了几个重要二进制命令:bochs(模拟器本身)、bxhub(虚拟网络环境)、bximage(创建虚拟磁盘)。
Bochs配置文件:
你是否以为文章快结束了?不,这仅仅只是个开始。