Ubuntu2204LTS 编译并安装 bochs2.6.11
阅读过《操作系统真象还原》的同学,都知道,要在 centos6 上编译并安装 bochs。但 centos6 实在太古老了。所以在豆包帮助下摸索着在 Ubuntu2204LTS 编译并安装 bochs2.6.11 成功,以期帮助同学们同学们减少弯路。
附录1、附录2告诉了我们:这也说明了,在 AI 时代,我们人均运维专家是问题不大的。就是 1)问题是否有解?无解那没辙。2)有解,则就是过程是否曲折的问题。
一、下载 bochs2.6.11 源代码
打开终端,使用 wget 命令直接下载源代码包(也可通过浏览器访问 Bochs 官网下载):
bash
wget https://downloads.sourceforge.net/project/bochs/bochs/2.6.11/bochs-2.6.11.tar.gz
解压源代码包到当前目录:
bash
tar -zxvf bochs-2.6.11.tar.gz
cd bochs-2.6.11
二、安装编译依赖工具和库
由于配置中启用了大量硬件模拟(如 USB、PCI、E1000 网卡等),需安装以下依赖库:
bash
sudo apt-get update
sudo apt-get install -y build-essential libgtk2.0-dev libsdl1.2-dev \
libncurses5-dev libx11-dev libxpm-dev libxrandr-dev libreadline-dev
三、修改源代码(解决驱动编译中的源代码与新编译器不匹配问题)
启用复杂硬件模拟时,Bochs 2.6.11 的部分源码与 Ubuntu 22.04 的编译环境存在兼容性问题,需手动修改两三个文件(具体见文末后附的解释及修改方法)。
四、配置编译选项
执行以下命令配置编译参数(启用调试器、64 位支持、硬件模拟等;这比《操作系统真象还原》上推荐的编译开关多了很多,也在文末解释):
bash
./configure \
--enable-debugger \
--enable-disasm \
--enable-x86-64 \
--enable-a20-pin \
--enable-smp \
--enable-cpu-level=6 \
--enable-long-phy-address \
--enable-pci \
--enable-usb \
--enable-usb-ohci \
--enable-e1000 \
--with-sdl \
--with-x11 \
--with-term
配置过程中若提示缺失依赖,根据提示安装对应库(如 libgtk2.0-dev 缺失则补充安装,话说在AI帮助下,只要有解,它就一定能帮你解决)。
五、编译源代码
执行 make 命令开始编译(耗时约 3-10 分钟,取决于硬件性能):
bash
make -j$(nproc)
这里使用多线程加速编译,$(nproc) 自动获取 CPU 核心数。编译过程中会显示各模块(如 CPU、USB、网络驱动)的编译日志,若出现错误,检查是否遗漏上述源码修改步骤。
六、安装 bochs
编译完成后,执行以下命令安装到系统目录:
bash
sudo make install
安装完成后,可在 /usr/local/bin 下找到 bochs(主程序)、bochsdbg(调试器)、bximage(镜像工具)等可执行文件。
七、验证安装
检查版本:
bash
bochs --version
若输出 Bochs x86 Emulator 2.6.11,说明安装成功。
我的目录结构:
home---vm---bochs
我bochs目录下bochsrc.txt内容如下:
plaintext
# ###############################################################
# # Bochs Configuration File - Version 2.6.11
# ###############################################################
# ================
# 系统内存和启动设置
# ================
megs: 32
boot: disk
# ================
# BIOS 和 ROM 设置 - 使用 $BXSHARE 环境变量
# ================
romimage: file=$BXSHARE/BIOS-bochs-latest
vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
# ================
# 输入设备设置
# ================
mouse: enabled=0
# keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-us.map
keyboard: type=mf, serial_delay=250, paste_delay=100000
# keyboard: type=mf, serial_delay=200, paste_delay=100000
# ================
# 存储设备设置
# ================
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="hd60M.img", mode=flat
ata0-slave: type=disk, path="hd80M.img", mode=flat
# ================
# 显示设置 (新增推荐项)
# ================
# 选择显示库: sdl, x, win32, term, wx, nogui
# display_library: sdl
display_library: sdl, options="gui_debug"
# ================
# 调试和日志设置
# ================
log: bochsout.txt
# ================
# 调试器设置 (可选)
# ================
# gdbstub: enabled=1, port=1234
运行后效果如下(我也忘了这是哪章的例子了):
调试界面效果如下,是不是比原先好看多了

通过以上步骤,即可在 Ubuntu 22.04 LTS 中成功编译并安装支持丰富硬件模拟的 Bochs 2.6.11,满足操作系统开发调试需求。
附 1:关于好几个多出来的开关的考虑
考虑到万一哪天我们需要做些较复杂系统,需要用到很多硬件的模拟时,configure 以下开关主要用于启用 Bochs 对特定硬件特性、CPU 架构、外设的模拟支持,适用于需要模拟更贴近真实 PC 环境的场景(如运行 64 位系统、多核心 CPU、PCI/USB 设备等),如果您没打开这些开关,大概率不会遇到需要修改源代码的情况。以下是每个开关的详细作用:
-
--enable-x86-64核心作用:启用对 x86-64 架构(64 位 CPU) 的模拟支持。场景需求:若你需要在 Bochs 中运行 64 位操作系统(如 64 位 Linux、Windows 10 64 位),必须启用此开关;若仅模拟 32 位系统(如 32 位 Linux、DOS),可省略此选项(默认仅支持 32 位 x86)。注意:启用后需确保后续 Bochs 配置文件(bochsrc)中指定 cpu: model=core2duo 等 64 位兼容 CPU 型号,否则 64 位系统无法启动。
-
--enable-a20-pin核心作用:模拟真实 PC 中的 A20 地址线控制引脚。背景知识:A20 引脚是早期 x86 架构中用于控制 “是否允许访问 1MB 以上内存” 的硬件开关(实模式下默认限制 1MB 内存,开启 A20 后才能进入保护模式 / 长模式访问大内存)。场景需求:虽然现代系统会自动处理 A20 引脚,但模拟早期操作系统(如 DOS、Windows 3.x)或调试操作系统内核(如实现保护模式切换)时,启用此选项能让硬件模拟更真实,避免因 A20 逻辑缺失导致的启动异常。
-
--enable-smp核心作用:启用 对称多处理器(SMP)模拟,即支持模拟多核心 CPU。场景需求:若需运行支持多核心的系统(如多线程 Linux、Windows 多核心版本),或调试多核相关的内核代码,必须启用此选项;启用后可在 bochsrc 中通过 cpu: count=2(模拟 2 核)、count=4(模拟 4 核)指定核心数。注意:需配合 --enable-cpu-level 指定支持 SMP 的 CPU 级别(如下文 --enable-cpu-level=6),否则多核心配置可能无效。
-
--enable-cpu-level=6核心作用:指定 Bochs 模拟的 CPU 功能级别,6 对应 Intel Core 2 架构(或同级别 AMD CPU)。级别含义(Bochs 中 cpu-level 数值对应架构):3:Intel 80386(早期 32 位 CPU,无 MMX/SSE 指令);4:Intel 80486(支持基本 32 位指令,无高级指令集);5:Intel Pentium(支持 MMX 指令集);6:Intel Core 2(支持 SSE/SSE2/SSE3 指令集、64 位扩展、SMP 多核心);7:Intel Nehalem(支持更高级指令集,如 SSE4.2、VT-x 虚拟化)。场景需求:启用 --enable-x86-64 或 --enable-smp 时,需将 cpu-level 设为 6 及以上(6 是 64 位和 SMP 的最低兼容级别),否则无法支持 64 位系统或多核心。
-
--enable-long-phy-address核心作用:启用对 64 位物理地址空间 的支持。场景需求:现代 PC 支持超过 4GB 的物理内存(如 8GB、16GB),此选项允许 Bochs 模拟 64 位物理地址总线,从而支持模拟大于 4GB 的内存(需在 bochsrc 中通过 memory: guest=8G 配置)。若仅模拟 4GB 及以下内存的系统,可省略此选项;但启用 --enable-x86-64 时,建议配合启用此选项以贴近真实 64 位硬件。
-
--enable-pci核心作用:启用对 PCI 总线(Peripheral Component Interconnect) 的模拟。背景知识:PCI 是现代 PC 中连接外设(如显卡、网卡、硬盘控制器)的核心总线,替代了早期的 ISA 总线。场景需求:若需模拟依赖 PCI 总线的设备(如后文的 e1000 网卡、USB 控制器),或运行需要识别 PCI 硬件的系统(如大多数现代 Linux/Windows),必须启用此选项;否则仅支持早期 ISA 设备,无法驱动现代外设。
-
--enable-usb核心作用:启用对 USB 总线 的基础模拟支持。注意:此选项仅开启 USB 总线框架,若需模拟具体 USB 设备(如鼠标、键盘、U 盘),还需配合启用对应的 USB 控制器驱动(如下文 --enable-usb-ohci)。场景需求:若需在 Bochs 中使用 USB 设备(如用 USB 鼠标操作 guest 系统),必须启用此选项;否则系统无法识别 USB 设备。
-
--enable-usb-ohci核心作用:启用对 OHCI 型 USB 控制器 的模拟(OHCI 是 USB 1.1 标准的控制器规范)。补充说明:Bochs 还支持其他 USB 控制器类型(如 --enable-usb-uhci 对应 UHCI 控制器、--enable-usb-ehci 对应 USB 2.0 的 EHCI 控制器),OHCI 是最基础、兼容性最广的类型,适合大多数场景。场景需求:需配合 --enable-usb 使用,否则无法驱动 USB 设备;若需模拟 USB 2.0 高速设备,可额外添加 --enable-usb-ehci。
-
--enable-e1000核心作用:启用对 Intel e1000 千兆网卡 的模拟。场景需求:若需在 Bochs 中实现 guest 系统(如 Linux)的网络功能(如联网下载、SSH 连接),必须启用此选项(或其他网卡模拟,如 --enable-ne2k 对应早期 NE2000 网卡);e1000 是现代千兆网卡,兼容性好(大多数系统自带驱动),比早期 NE2000 更贴近真实硬件,推荐优先选择。
另外,因为都 2025 年了,bochs 也早就支持图形化的调试了,比控制台上命令行好用多了,所以特意加入图形界面开关。
-
--with-sdl用于启用 SDL(Simple DirectMedia Layer)图形接口支持 的开关,其作用是让 Bochs 能够通过 SDL 库渲染虚拟机的图形界面(如模拟的显示器输出)。SDL 是一款跨平台的多媒体库,支持窗口创建、图形绘制、输入处理等功能,Bochs 依赖它实现更灵活的图形输出(尤其在没有 X11 环境时也能工作)。为什么需要 --with-sdl?兼容性:SDL 支持更多环境(如无 X11 的终端、嵌入式系统),若仅用 --with-x11,在纯命令行环境下 Bochs 可能无法显示图形界面。功能补充:SDL 对输入设备(如鼠标、键盘)的模拟更稳定,尤其在调试操作系统时,能更准确地传递输入事件到虚拟机。应注意:--with-sdl 并非独立生效,它需要系统中已安装 SDL 1.2 开发库,否则会出现依赖失败(前面第 “二” 步已经加上了)。
-
其他与图形相关的其他配置开关(可选)--with-x11启用 X11 图形接口支持(与 SDL 二选一或同时启用,Bochs 会优先使用 X11 若可用)。依赖 libx11-dev、libxpm-dev 等 X11 开发库(前面第 “二” 步已经加上了);
附 2:关于修改源代码中的错误
上述描述,是直接跳过弯路的步骤,这里描述下当初编译出错及解决方案。从输出日志来看,主要遇到两类问题:警告(Warnings) 和两三个错误(Error),其中错误导致编译中断。以下是具体分析和解决方法:
- 错误 bx_debug/dbg_main.cc 中 this 指针错误在 bx_debug/dbg_main.cc 中出现编译错误:
plaintext
../cpu/cpu.h:383:28: error: invalid use of ‘this’ in non-member function
383 | # define BX_CPU_THIS_PTR this->
| ^~~~
../cpu/tlb.h:62:32: note: in expansion of macro ‘BX_CPU_THIS_PTR’
62 | #define BX_ITLB_INDEX_OF(lpf) (BX_CPU_THIS_PTR ITLB.get_index_of(lpf))
| ^~~~~~~~~~~~~~~
dbg_main.cc:1497:18: note: in expansion of macro ‘BX_ITLB_INDEX_OF’
1497 | Bit32u index = BX_ITLB_INDEX_OF(laddr);
原因:BX_CPU_THIS_PTR 宏依赖于 this 指针(属于类成员函数的上下文),但在 dbg_main.cc 的非成员函数中使用了该宏,导致上下文冲突。本质:Bochs 2.6.11 与较新的 GCC 编译器(尤其是支持 C++11 及以上标准的版本)存在兼容性问题,旧代码中的宏定义未考虑现代编译器的严格检查。解决方法修改代码修复错误打开文件 bx_debug/dbg_main.cc,找到报错的行(1497 和 1501 行附近):
cpp
运行
运行
Bit32u index = BX_ITLB_INDEX_OF(laddr); // 1497行
index = BX_DTLB_INDEX_OF(laddr, 0); // 1501行
替换这两行代码(绕过 BX_CPU_THIS_PTR 宏的问题):
cpp
运行
运行
// 注释掉原来的两行,替换为:
Bit32u index = BX_CPU(0)->ITLB.get_index_of(laddr);
index = BX_CPU(0)->DTLB.get_index_of(laddr, 0);
原理:直接通过 BX_CPU (0) 获取 CPU 实例,避免使用依赖 this 指针的宏。
- harddrv.cc 中 controller_t 结构体无 error_ 成员错误错误信息:
plaintext
harddrv.cc:260:37: error: ‘struct controller_t’ has no member named ‘error_’
260 | BX_CONTROLLER(channel,device).error_= 0x01; // diagnostic code: no error
原因:Bochs 2.6.11 的代码中,controller_t 结构体可能已移除或重命名了 error_ 成员,但代码中仍在使用该成员,导致编译错误。解决方法:将所有 controller->error_ 或 BX_CONTROLLER (...).error_ 替换为 controller->error(去掉末尾的下划线)。具体步骤:打开文件 iodev/harddrv.cc:
bash
nano iodev/harddrv.cc
全局搜索 error_,将所有出现的 error_ 替换为 error(例如 controller->error_ → controller->error,BX_CONTROLLER (...).error_ → BX_CONTROLLER (...).error)。保存并退出。
- vgacore.cc 中 read_data_ 和 write_data_ 成员不存在错误错误信息:
plaintext
vgacore.cc:1053:25: error: ‘struct ...’ has no member named ‘read_data_’; did you mean ‘read_data_cycle’?
1053 | BX_VGA_THIS s.pel.read_data_= value;
vgacore.cc:1059:25: error: ‘struct ...’ has no member named ‘write_data_’; did you mean ‘write_data_cycle’?
原因:VGA 核心结构体中的成员 read_data_ 和 write_data_ 可能已重命名为 read_data_cycle 和 write_data_cycle(编译器提示的建议)。解决方法:按照编译器提示的建议替换成员名:打开文件 iodev/display/vgacore.cc:
bash
nano iodev/display/vgacore.cc
找到第 1053 行,将 s.pel.read_data_ 替换为 s.pel.read_data_cycle。找到第 1059 行,将 s.pel.write_data_ 替换为 s.pel.write_data_cycle。说实话,当初看到这些错误时,一度想放弃。我何德何能,居然能改这样的 Bug?但在豆包帮助下,居然搞定了,实在令人惊叹!!关于 2、3,不想进入代码改,可在控制台用如下命令直接替换:
bash
# 修改 harddrv.cc 中的 error_ 为 error
sed -i 's/error_/error/g' iodev/harddrv.cc
# 修改 vgacore.cc 中的成员名
sed -i 's/read_data_/read_data_cycle/g' iodev/display/vgacore.cc
sed -i 's/write_data_/write_data_cycle/g' iodev/display/vgacore.cc
4、vgacore.cc:成员名拼写错误(多了冗余后缀)错误信息示例:
plaintext
vgacore.cc:298:75: error: ‘...’ has no member named ‘write_data_cycleregister’; did you mean ‘write_data_register’?
vgacore.cc:299:72: error: ‘...’ has no member named ‘write_data_cyclecycle’; did you mean ‘write_data_cycle’?
原因:代码中错误地使用了冗余后缀(如 cycleregister、cyclecycle),正确的成员名应为 register 或 cycle(编译器已提示建议)。解决方法:全局替换错误的成员名,去掉冗余的 cycle 前缀:打开文件 iodev/display/vgacore.cc:
bash
nano iodev/display/vgacore.cc
执行以下替换(可通过编辑器的全局替换功能):write_data_cycleregister → write_data_registerwrite_data_cyclecycle → write_data_cycleread_data_cycleregister → read_data_registerread_data_cyclecycle → read_data_cycle保存并退出。
- harddrv.cc:controller_t 无 error 成员,errorrecovery_t 命名错误错误信息示例:
plaintext
harddrv.cc:260:37: error: ‘struct controller_t’ has no member named ‘error’
harddrv.cc:1413:82: error: ‘errorrecovery_t’ was not declared in this scope; did you mean ‘error_recovery_t’?
harddrv.cc:3620:1: error: ‘errorrecovery_t’ does not name a type; did you mean ‘error_recovery_t’?
原因:controller_t 结构体中实际成员名为 error_register(带下划线),而非 error。类型名 errorrecovery_t 应为 error_recovery_t(带下划线)。解决方法:打开文件 iodev/harddrv.cc:
bash
nano iodev/harddrv.cc
替换 controller->error 和 BX_CONTROLLER (...).error 为 controller->error_register 和 BX_CONTROLLER (...).error_register(添加 _register 后缀)。替换所有 errorrecovery_t 为 error_recovery_t(添加下划线)。保存并退出。操作步骤总结同样的,关于 4、5,不想进入代码改,可在控制台用如下命令直接替换通过 sed 命令批量替换可快速解决:
bash
# 修复 vgacore.cc 中的成员名错误
sed -i 's/write_data_cycleregister/write_data_register/g' iodev/display/vgacore.cc
sed -i 's/write_data_cyclecycle/write_data_cycle/g' iodev/display/vgacore.cc
sed -i 's/read_data_cycleregister/read_data_register/g' iodev/display/vgacore.cc
sed -i 's/read_data_cyclecycle/read_data_cycle/g' iodev/display/vgacore.cc
# 修复 harddrv.cc 中的 error 成员和类型名错误
sed -i 's/controller->error/controller->error_register/g' iodev/harddrv.cc
sed -i 's/BX_CONTROLLER(.*).error/BX_CONTROLLER\1.error_register/g' iodev/harddrv.cc
sed -i 's/errorrecovery_t/error_recovery_t/g' iodev/harddrv.cc
6、因为前面替换,可能 harddrv.cc 中出现了因之前替换操作导致的新错误(如 error_register_register 这种重复后缀的错误命名),以及未完全修复的成员名问题。以下是针对性的解决方法:核心问题分析错误的重复替换导致成员名无效:之前的替换操作可能重复添加了 _register 后缀,导致出现 error_register_register 这种不存在的成员名(正确名称应为 error_register)。未完全修复的 BX_CONTROLLER (...) 成员:日志中仍有 BX_CONTROLLER (channel,device).error 错误,说明此类结构的成员未正确替换为 error_register。cdrom_t::current.errorrecovery 命名错误:应替换为 error_recovery(带下划线)。解决步骤修复 harddrv.cc 中的重复后缀错误将所有误生成的 error_register_register 替换为正确的 error_register:
bash
sed -i 's/error_register_register/error_register/g' iodev/harddrv.cc
修复 BX_CONTROLLER (...) 结构体的 error 成员将 BX_CONTROLLER (...) 中的 .error 替换为 .error_register:
bash
sed -i 's/BX_CONTROLLER(\([^)]*\)).error/BX_CONTROLLER(\1).error_register/g' iodev/harddrv.cc
修复 cdrom_t 中的 errorrecovery 成员将 errorrecovery 替换为 error_recovery:
bash
sed -i 's/errorrecovery/error_recovery/g' iodev/harddrv.cc
修复 errorregister 拼写错误将 errorregister 替换为 error_register(添加下划线):
bash
sed -i 's/errorregister/error_register/g' iodev/harddrv.cc
注:我实在懒得分析,为什么引入了新错误?如果您有同样问题,按这里步骤改就好啦。
7、也因为前面替换,可能引入 harddrv.cc 中存在两处因拼写错误导致的编译错误,具体如下:错误分析错误信息:
plaintext
harddrv.cc:622:75: error: ‘struct controller_t’ has no member named ‘error_registerregister’; did you mean ‘error_register’?
harddrv.cc:1034:64: error: ‘struct controller_t’ has no member named ‘error_registerregister’; did you mean ‘error_register’?
原因:成员名被错误地重复添加了 register 后缀,导致出现 error_registerregister 这种无效名称,正确名称应为 error_register(编译器已提示)。解决方法通过 sed 命令批量替换错误的成员名:
bash
# 将错误的 "error_registerregister" 替换为正确的 "error_register"
sed -i 's/error_registerregister/error_register/g' iodev/harddrv.cc
至此,所有的错误都得到改正。实际上真正的错误就是 1、2,其余都是在修改中引入的新问题。
更多推荐


所有评论(0)