我们上面提到的Virtual PC和VMware都是商业软件,而下面将要介绍的Bochs软件则是开源的和免费的。可以从http://bochs.sourceforge.net/获取它的最新版本和相关信息。
2.7.1 Bochs vs. Virtual PC vs. VMware
不知道开源给你的感觉是什么,对笔者而言,它总是意味着亲切、清新,身上没有讨厌的商业气息。也许你也有同感,如果是的话,可能你已经对本书到现在才提到Bochs感到不满。实际上笔者对Bochs其实是充满好感的,尤其是它可以对操作系统进行调试,这样方便的特性不能不让我们对它青睐有加。理论上讲,Bochs可以完全取代Virtual PC和VMware,但以笔者个人的体会,从一个操作系统开发者的角度来看,Bochs大致有这么几个缺点:
— Virtual PC有共享文件夹功能,可以方便地读取host上的文件,而Bochs不可以。当我们学习保护模式时,免不了要用到DOS,用Virtual PC可以在Windows下编写代码,通过共享文件夹的方式在DOS下执行,而Bochs就没这么方便。
— 跟Virtual PC和VMware比起来,Bochs的速度要慢得多,笔者曾经试图在Bochs上安装Red Hat 9,但随后就发现这是个愚蠢的决定,太慢了,不久笔者就把它中止掉了。
— Virtual PC的图形化界面要比Bochs好用。
读者可能注意到了上文中“从一个操作系统开发者的角度来看”这一句,之所以这样说,是因为我们这样武断地将Bochs拿来跟Virtual PC或Vmware相比是不公平的。虽然它们模拟同一个操作系统时的输出可能差不多,但从实现机制上讲,它们有巨大的不同。
Bochs是一个模拟器,它完全模拟x86的硬件以及一些外围设备。而VMware除了模拟一些特定的I/O之外,还可以用它的x86运行时引擎来完成其余内容的执行。意思是说,当客户PC试图执行一些动作时,VMware并不是利用自己重造的机制来解释它,而是将它传递给实际的硬件。在这里,VMware的工作更应称为“虚拟(virtualize)”而不是“模拟(emulate)”。Virtual PC的原理介于两者之间,它的一些部分是模拟出来的,另一部分则是虚拟出来的。Virtual PC能够实现共享文件夹也是因为同样的原因。
由于Bochs在模拟一台真正的机器的硬件,所以使得它比VMware和Virtual PC都慢得多。
笔者曾经将Tinix分别用Bochs 2.1.1、Virtual PC 5.0、VMware 3.2.0和真实的机器进行比较测试,发现在Virtual PC上运行的效果跟真实的机器居然差不多,而Bochs和VMware则慢得多,这可能跟它们实现机制的差异以及Tinix自身的特点有关。不过,Virtual PC的确因为速度、操作方便性等特点具备很强的吸引力,以至于本书最终将它而不是开源免费的Bochs作为首选。
那么Bochs是不是就被我们抛弃了呢?当然不是,因为Bochs的调试功能实在太令人兴奋了。当我们的操作系统出现问题时,Bochs就变得无法替代。下面,我们就来看一下,Bochs到底如何使用。
2.7.2 Bochs的使用方法
我们先来一点感性认识,首先从http://bochs.sourceforge.net/获取Bochs的安装程序。这里以Bochs 2.1.1为例,安装完成后,在菜单中可以找到快捷方式Linux Demo in Bochs 2.1.1,双击它,几秒钟之后,如图2-44所示的画面出现了。

图2-44 用Bochs启动Linux
感觉怎么样?虽然你已经熟悉了虚拟机这种东西,看到这样的画面还是感到很有趣,不是吗?这是一个非常小的Linux,输入root,然后按回车键,就可以登录进去使用了。如图2-45所示。

图2-45 登录到root
新奇之后,让我们来看看这奇妙的过程是怎么发生的。
首先在桌面上找到快捷方式Linux Demo in Bochs 2.1.1,看看它的目的地:D:\Program Files\Bochs-2.1.1\dlxlinux\run.bat。现在,就让我们看看run.bat的内容:
cd "d:\Program Files\Bochs-2.1.1\dlxlinux"
..\bochs -q -f bochsrc.bxrc
原来Bochs通过bochs -q -f bochsrc.bxrc这样的命令行来启动,那么不用说,启动的各种参数一定就装在bochsrc.bxrc中,下面就让我们来看一下(为节省篇幅,省略了部分内容):
代码2-1 bochsrc.bxrc(请参考\chapter2\bochsrc.bxrc)
# how much memory the emulated machine will have
megs: 32
# filename of ROM images
romimage: file=$BXSHARE/BIOS-bochs-latest, address=0xf0000
vgaromimage: $BXSHARE/VGABIOS-elpin-2.40
# what disk images will be used
floppya: 1_44=floppya.img, status=inserted
floppyb: 1_44=floppyb.img, status=inserted
# hard disk
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="hd10meg.img", cylinders=306, heads=4, spt=17
# choose the boot disk.
boot: c
……
# where do we send log messages?
log: bochsout.txt
# disable the mouse, since DLX is text only
mouse: enabled=0
# enable key mapping, using US layout as default.
……
keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-us.map
内容看起来虽然不少,但是除去以#开头的注释之外,实际起作用的内容并不多,而且凭借字面意思,还是比较容易理解的。
你一定蠢蠢欲动地想把你的Boot Sector拿到这里试一下了,好的,我们就在Bochs- 2.1.1\目录下新建一个目录Tinix\,然后把Bochs-2.1.1\下面的内容全部复制过来,再把我们之前已经做好的Tinix.img复制到这里。好了,打开bochsrc.bxrc,将上面代码中用阴影标出的两行改为:
floppya: 1_44=Tinix.img, status=inserted
以及
boot: a
然后修改一下run.bat:
cd "d:\Program Files\Bochs-2.1.1\Tinix"
..\bochs -q -f bochsrc.bxrc
运行,结果如图2-46所示。

图2-46 用Bochs运行引导扇区
画面有点乱,那是因为Boot Sector没有进行任何的清屏操作,不过毫无疑问,红色的“Hello, OS world”已经出现在眼前,这表明运行成功了,整个操作就是这么简单。在本书附送光盘中的文件夹“\chapter2”中有相应的bochsrc.bxrc和run.bat文件供读者参考。
当然,Bochs的使用不止这么简单,就让我们在实际应用过程中慢慢学习吧。
2.7.3 用Bochs进行调试
用Bochs可以对操作系统进行调试,对于这一点,我们将在5.4.5.2节中再具体介绍。
2.7.4 在Linux上开发
或许你是个不折不扣的开源爱好者,对Linux无比热爱,并且决不肯对任何人妥协,没问题,运用Bochs使得在Linux上的开发变得与刚才介绍的情况非常类似。而且可以想像,在真正的Linux上编译我们的代码一定是非常快的。
为简单起见,我们从http://bochs.sourceforge.net/处直接获得Bochs的RPM包,然后安装,如图2-47所示。

图2-47 在Linux中安装Bochs 2.1.1
然后修改文件bochsrc.bxrc,涉及到的主要是相关路径:
代码2-2 在Linux下使用的bochsrc.bxrc
romimage: file=/usr/local/share/bochs/BIOS-bochs-latest, address =0xf0000
vgaromimage: /usr/local/share/bochs/VGABIOS-elpin-2.40
floppya: 1_44=tinix.img, status=inserted
floppyb: 1_44=floppyb.img, status=inserted
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="hd_dos.img", cylinders=101, heads=16, spt=63
boot: a
log: bochsout.txt
mouse: enabled=0
keyboard_mapping: enabled=1, map=/usr/local/share/bochs/keymaps/ x11-pc-us.map
这样就可以运行了,运行结果如图2-48所示。

图2-48 用Bochs运行引导扇区(在Linux平台下)
可以看到,与在Windows下的运行几乎是一摸一样的,不是吗?
另外,在Linux中使用软盘映像也非常方便,通过类似这样的命令就可以了:
mount /home/TINIX.IMG /mnt/floppy -o loop
总结一下,在Linux上开发可以通过这样的方式:
— GCC编译生成内核。
— 用mount命令将.IMG文件挂载到文件系统。
— 将内核复制到.IMG文件中。
— 用Bochs运行Tinix(可能需要先从文件系统中卸载.IMG文件)。
我们已经介绍了这么多,从Virtual PC到Bochs,从Windows到DOS,再到Linux,其实,简言之,在最简陋的条件下,我们只要有一个Linux平台和一张软盘就够了,其他什么工具也不用,只是调试起来比较麻烦罢了。介绍这些工具的目的只不过是让开发环境用起来比较顺手,使我们的精力能够专注到问题的重点上,而不至于让一些操作上的细节占用太多的时间。无论哪一种工具和方法,只要能让你感到得心应手就够了。
对笔者而言,比较习惯于这样进行操作系统的开发:
— 在Windows下编写代码,使用Edit Plus等编辑器。
— 使用Linux的虚拟机编译内核和生成操作软盘映像。
— 必要时使用安装了DOS的虚拟机来调试程序以及操作软盘映像。
— 安装一个Bochs,必要的时候用它来调试。
— 使用其他必要的工具,比如版本控制工具(VSS或者CVS)。
有了这些好用的工具,我们就真正做到了“武装到牙齿”,从此尽可奋勇杀敌,一切无忧!那么,我们是不是马上就可以冲锋陷阵了呢?很遗憾,还不能那么着急,因为你知道,操作系统是跟硬件紧密相连的,如果想实现一个运行在使用IA32架构的IBM PC上的操作系统,免不了要具备相关的知识储备。其中的重头戏就是32位Intel CPU的运行机制,毕竟CPU是一台计算机的大脑,也是整个计算机体系的核心。
所以紧接着我们要学习的,就是要了解IA32保护模式。掌握了保护模式,我们才知道Intel的CPU如何运行在32位模式之下,从而才有可能写出一个32位的操作系统。
如果读者已经掌握了保护模式的内容,可以直接跳到第4章。