本节书摘来自异步社区《操作系统真象还原》一书中的第1章,第1.3节,作者:郑钢著,更多章节内容可以访问云栖社区“异步社区”公众号查看
1.3 操作系统的宿主环境
操作系统虽然是软件,但其可不是一般的软件。我们平时写出来的程序都是基于操作系统之上的,程序本身是由操作支持的,开发人员只要专注于自己这块业务逻辑就好了,很多复杂的问题是不需要开发人员考虑的。而操作系统这个软件靠谁来支持呢?是靠你自己……这是用一身老骨头扛出来的,现在明白为什么Linux之父Linus那么强壮了吧,不是谁都能随随便便成功的,所以,写操作系统那可是要有个好身板,要多锻炼身体才能熬得住,看完这章赶紧出去跑步吧,玩笑玩笑。如果一般应用软件能称得上鱼香肉丝的话,那操作系统得相当于龙虾鲍鱼,这可是硬菜,不出去跑个几公里都啃不下来呢。哈哈,其实也没那么夸张,现在有很多计算机大牛写了好多开源软件帮助我们调试操作系统。话说,自从有了虚拟机,我再也用不着锻炼身体了,每次出现bug时不需要重启真机了,只需要重启虚拟机就好。
1.3.1 什么是虚拟机
虚拟机在当今已经不是陌生的概念了,要是在几年前,我还得搬出个概念放在这给大家看看。个人觉得,要解释一个东西是什么,不如直接解释这个东西解决了哪些问题,这样大家自然就从本质上真正理解了它是什么。
没有虚拟机的时候,一台机器只有交给一个用户使用,而且一个人根本无法将这台机器的性能完全发挥出来,造成了极大的浪费不算,还有很多人正等着用呢。于是出现了虚拟机的需求:将一台物理机通过软件逻辑分割成几个虚拟的计算机,每个计算机之间互不干涉,即使一台虚拟计算机崩溃了也只是影响了它自身,不会让整个物理机瘫痪,安全可靠,可以自由测试而不必担心损伤物理机。这不仅在硬件投入上节省了大笔开销,还让更多的人同时使用了计算机资源。
现在很多厂商都在搞虚拟化,如域名的虚拟空间,还有如火如荼的阿里云,这是虚拟机的应用。虚拟机就是用软件来模拟硬件。虚拟机只是一个普通的进程,该进程模拟了硬件资源,在虚拟机中运行的程序其所做出的任何行为都先被虚拟机检查,由虚拟机分析后,代为向操作系统申请。
上面对虚拟机的解释是主观上的理解,我可不愿意说概念了,因为概念是对事物的抽象。抽象就意味着不易理解,容易把简单的事复杂化。我举个简单的例子来说明什么是虚拟机。
假设V是虚拟机进程,U是普通的用户程序。程序运行起来才叫进程,进程是要有pcb的,程序老实地放在磁盘上不动,那可不叫进程。虚拟机跑起来后,就形成了进程V,在它被调度期间,CPU执行的是此进程中的指令。让虚拟机执行U程序,有如解释器进程在解析脚本文件一样,此时的U程序被当作参数传给了V程序,U程序就像文章一样由V进程阅读。还是拿解释型语言举例子,比如python语言,其脚本从来就没有直接作用于CPU上,而是将其字节码交给了python解释器,这个解释器将通过python虚拟机来代为完成python脚本中的代码行为。
让我们说得再具体一点,比如在Linux平台上,写了一个python脚本文件file.py,其中有这样一句代码:fh=open(“hello.txt”,'w'),这是在用可写的方式打开hello.txt文件,将其句柄返回给fh。自此操作文件句柄fh便操作了文件hello.txt。python虚拟机是一个进程,它是直接作用在硬件之上的。当它分析python脚本file.py中上面的那句代码时,发现有关键字open(当然关键字得是python解释器支持的,此解释器为它们而生才行),于是执行了open(“hello.txt”,'w')函数,其内部是封装的系统调用(系统调用这方面内容以后咱们在自己的系统中细说),通过系统调用,python虚拟机替python脚本完成了打开hello.txt的工作。
选择虚拟机的原因如下。
1.运行方便
它在宿主系统上只是一个进程,在宿主系统如Linux眼里,它与一般的用户进程是没任何区别的。进程咱们都可以随意启动,虚拟机也是一样的,在这一点保证了使用上的方便性。
2.保护计算机
如果您有一般的软件开发经验,就会了解,很少有程序能一下就编译通过。当然,如果您的编程经验无比丰富,代码无比规范,无比了解编译器,确实不需要虚拟机来调试了,编写完成后直接就能运行。以上我用了三个“无比”,打造了似乎没有人能达到这种水平的假象,其实是有的。不知道大家听说过Jon Skeet没有,他是谷歌软件工程师,《C# In Depth》就是他的作品。看看别人对他是怎样评价的,看完之后您就知道我说的并不夸张了。
“他并不需要调试器,只要他盯着代码看几眼,Bug自己就跑出来了”。
“他根本不需要什么编程规范,他的代码就是规范”。
“如果他的代码没有通过编译,编译器厂商就会道歉”。
如果咱们都不能保证写出这样质量出色的代码,咱们还是老老实实地装虚拟机吧。因为如果要把操作系统装在真机器上,每次调试的时候,无论代码是否崩溃,都是要重启计算机的。为了保护咱们的爱机,虚拟机必装不可。不知道你们心疼电脑吗,反正我要是一天开电脑三次以上,我就会很自责,不知道这种性格和水瓶座有没有关系。
说了虚拟机的好处,那咱们有哪些虚拟机可用呢。一般的有qemu、bochs、virtualBox、xen和vmware等。
大家都这么忙,能有时间拿起书不容易啊,为了不浪费您宝贵的时间,我就不说和本书不相关的虚拟机了,种类再多,也只是选一个。我们要用的就是bochs。选择bochs的理由如下。
(1)开源,有感于作者的奉献精神,我们要支持作者(当然qemu也是)。
(2)支持调试,不仅原生支持调试,还支持gdb远程调试(当然qemu也是)。
(3)我只会这个。
对于虚拟机的选择,能工作能调试够用就行了,遇到问题时再寻求新方案也不迟,毕竟咱们的重点是后面的写操作系统,学太多的虚拟机也没啥用。
介绍一下bochs吧,怎么也得让大家有个初步的印象。下面的内容是我从维基百科翻译过来的,其实就是从繁体中文翻译成了简体中文,而且只有几个繁体字,哈哈。
Bochs(发音:box)是一个以LGPL许可证发放的开放源代码的x86、x86-64IBM PC兼容机模拟器和调试工具。它支持处理器(包括保护模式)、内存、硬盘、显示器、以太网、BIOS、IBM PC兼容机的常见硬件外设的仿真。
许多客户操作系统能通过该仿真器运行,包括DOS、Microsoft Windows的一些版本、AmigaOS 4、BSD、Linux、MorphOS、Xenix和Rhapsody(Mac OS X的前身)。Bochs能在许多主机操作系统运行,例如Windows、Windows Mobile、Linux、Mac OS X、iOS和PlayStation 2。
Bochs主要用于操作系统开发(当一个模拟操作系统崩溃,它不崩溃主机操作系统,所以可以调试仿真操作系统)和在主机操作系统运行其他来宾操作系统。它也可以用来运行不兼容的旧的软件(如电脑游戏)。
它的优点在于能够模拟跟主机不同的机种,例如在Sparc系统里模拟x86,但缺点是它的速度却慢得多。
介绍完了,不知道您看了吗,不看也行,反正以后咱们实际应用时还会细说的。
1.3.2 盗梦空间般的开发环境,虚拟机中再装一个虚拟机
很多同学电脑的系统都是Windows,个别的是Mac OS,还有的同学用的是Linux。作为一名Linux粉丝,我的开发环境必然建立在Linux平台下。那对于其他系统的用户,你们可以自己部署相应平台的开发环境,用的工具都是一样的,无非是换个相应平台的版本。不过我担心由于平台不同而造成这样那样的问题,会减退大家学习的积极性,毅力不足的同学还没开始写操作系统就急流勇退了,我后面精彩的内容没有观众该怎么办。为了减少学习的困难,也为了让大家继续为我后面的内容捧场,我在睡觉的时候想到一个好办法,能让大家的开发环境极大限度地得到统一,就是我们加一层,再安装一个虚拟机。
首先虚拟机是个软件,不会伤害咱们的爱机。我一度认为虚拟机是一项非常伟大的发明,甚至认为它是给像我这样的穷人最好的礼物,当初学习思科(网络、路由器等方面知识)时,幸亏有虚拟机来模拟多台计算机,否则还真买不起第二台电脑,所以大家一定要好好学习,不要像我当初那样辜负了虚拟机。我们的方案是这个虚拟机就用virtualBox吧,虽然在结尾加了个“吧”,但我丝毫没有征求大家意见的意思,哈哈,抱歉,我这也绝对不是强硬。让小弟我给大家个交待。
(1)个人觉得virtualBox比vmware更轻量,配置起来更简单。
(2)virtualBox是免费的,不需要破解,这一点很重要。
(3)因为我不想改成别的了,嫌麻烦,请大家原谅。
交待过了之后,大家还是根据自己喜好选择虚拟机,大家觉得哪个方便就用哪个。
方案再多也总该选择一个,我选择的方案是在virtualBox中安装个操作系统。因为要在Linux下开发,所以选的是与redhat很接近的CentOS,我用的版本是6.3,本书中以后便以virtualBox+CentOS 6.3为例。由于我后续的环境部署都是在此版本上进行的,没遇到什么大问题,确实感觉很稳定,简单可依赖。
在CentOS中再装个bochs,最终我们的代码运行在bochs中。
想当初莱欧纳多的电影《盗梦空间》上映时,很多朋友都被故事的新颖所吸引,大概意思是通过潜入别人的梦中去窃取机密,如果第一层梦境窃取不到,还可以在梦中继续睡觉,再进入第二层,也就是梦中梦。这就是标题中所说的,虚拟机中再装个虚拟机,您看,描述还是有些形象的。
1.3.3 virtualBox下载,安装
virtualBox官方下载地址是http://download.virtualbox.org/virtualbox
,大家选择一个适合自己系统平台的版本,我安装的是4.2.12 mac版本,具体下载地址是http://download.virtualbox.org/virtualbox/4.2.12/
,大家可以自行选择。
MacOS和Windows基本上virtualBox的安装是一路回车,没什么可说的。如果您用的系统是Linux,我更觉得说什么都显得多余,因为能用Linux办公,说明您完全有能力安装成功。
1.3.4 Linux发行版下载
可以在mirrors.163.com这个国内的镜像源去下载自己喜欢的版本。
由于CentOS官方的告示,目前6系列的版本只有6.5可用,其他低版本不再支持。喜欢CentOS的朋友可以趁机装个新版本。如果您像我一样执拗非6.3版本不装,我也给出了官方的链接地址,大家斟酌安装。
http://vault.centos.org/6.3/isos/i386/CentOS-6.3-i386-bin-DVD1.iso
大家根据自己虚拟机的种类开始安装Linux吧,由于版本和宿主系统种类较多我不便将安装步骤一一给出,大家若有不懂的问题请自行查阅,百度经验上有很多方法,若第一次用虚拟机,大家可以参考下面链接的方法。
http://jingyan.baidu.com/article/414eccf61d12cc6b431f0ae7.html。
1.3.5 Bochs下载安装
在完成了Linux发行版的安装后,现在到了安装bochs的环节,这是我们的操作系统最终的宿主机。
由于我的工作是运维,所以练就了任何软件包都要从源码安装的“陋习”,从来不信任任何软件包。因为只有从源码安装的版本才会在其配置和编译过程中根据所在的平台的特性去优化,这些是其他形式的软件包不可比拟的。举个例子,将别人的Windows系统直接ghost到自己的机器上和从光盘安装Windows比,哪个装的Windows系统用得更稳定,哪个安装方法能让Windows坚持到半年才重装一次……我不能再说了,我作为Linux粉丝的事实已表露无遗。虽然我个人偏爱Linux,但绝对不能否认,是Windows把我带入计算机世界的。这个IT世界若没有Windows将暗淡70%的光芒。其实原先我写的是90%,我怕有人问我这个数是怎么来的,这是我一拍脑门随口说出来的,所以我稳妥起见改为了70%,总之,不能无视Windows的伟大功绩。
bochs的安装相对要麻烦一些,不光是装上去就行了,还需要配置一下。
软件包得传到虚拟机上才能安装到虚拟机里,如何传上去呢。下面建议了3个方案。
(1)给虚拟机装个ftp,通过ftp上传。
(2)让虚拟机连网,直接下载。
(3)虚拟机支持USB,通过U盘上传软件包。
第1个方案需要配置ftp服务器,我用的是proftpd,相对来说有点麻烦,也是需要单独配置的。而且默认Linux的iptables会有一些规则,需要手动将其关闭。
第2个方案较简单,在您的宿主系统可以连网的情况下,需要您自己配置一下virtualBox的网卡,将网卡部分改为NAT可以通过宿主系统连网,将网卡改为桥接可以直接连网。由于大家的版本不统一,虽然不知道界面是否接近,但菜单名称总该是一样的。我用的是mac版virtual Box,给大家截个图看看,如图1-1所示。
将网卡模式改为NAT后,虚拟机就可以连网了。
第3个方案最方便了,大家自己试一下吧。
好了,下面就假设大家能够把安装包上传到虚拟机中,安装走起。
1.下载bochs
官方地址是http://sourceforge.net/projects/bochs/files/bochs/
,我安装的版本是2.6.2,下载后的文件是bochs-2.6.2.tar.gz。
2.解压压缩包tar zxvf bochs-2.6.2.tar.gz
3.编译
先进入到目录cd bochs-2.6.2,开始configure、make、make install三步曲。
./configure \
--prefix=/your_path/bochs \
--enable-debugger\
--enable-disasm \
--enable-iodebug \
--enable-x86-debugger \
--with-x \
--with-x11
注意各行结尾的''字符前面有个空格。下面简要说明一下configure的参数。
--prefix=/your_path/bochs是用来指定bochs的安装目录,根据个人实际情况将your_path替换为自己待安装的路径。
--enable-debugger打开bochs自己的调试器。
--enable-disasm 使bochs支持反汇编。
--enable-iodebug启用io接口调试器。
--enable-x86-debugger支持x86调试器。
--with-x使用x windows。
--with-x11使用x11图形用户接口。
上面的编译参数是不支持gdb远程调试的,如果想用gdb调试,就要将参数--enable-debugger替换为--enable-gdb-stub。
--enable-gdb-stub用来打开对gdb的支持,这样我们就可以用gdb来远程调试了。
不过,需要注意的是不能同时打开这两个开关,否则bochs会报错,即configure:error:--enable-debugger and --enable-gdb-stub are mutually exclusive。
也就是说,bochs本身是支持调试的,要么用本身的调试功能,要么用gdb的调试功能,鱼和熊掌在一台模拟器上不可兼得。我说的是一台模拟器上不可兼得,所以,如果您愿意的话,可以用这两个参数各编译一版,只要--prefix指向不同的路径就行了,想用哪个就启用哪个。
不过我在开发过程中,只用过不超过5次的gdb调试,还是习惯bochs自己的调试功能,个人觉得它更强大,调试粒度更细微,反而更灵活。个人建议,直接用给出的configure参数就行,不要打开--enable-gdb-stub。
configure之后,会生成Makefile,可以开始编译了。
make
若编译时没有问题,就直接执行下面这句。
make install
完成安装。
补充一下,在编译用bochs调试功能的版本时(用--enable-debugger),曾经安装失败过,如果您也在安装过程中失败了,恰好出现类似下面的报错:
undefined reference to 'pthread_create'
undefined reference to 'pthread_join'
您可以按照下面的方法解决。如果不是这个报错,亲,您可能要辛苦一下自行解决啦。
上面报错的原因:
pthread库不是Linux系统默认的库,连接时需要使用静态库 libpthread.a,所以在使用pthread_create()创建线程,以及调用 pthread_atfork()函数建立fork处理程序时,需要链接该库。
解决方案:
在编译中要加 -lpthread参数。用vim编译makefile,vim是Linux下功能最为强大的文本编辑器。vim Makefile回车:
编辑第92行,将thread库加入,将其放在行末尾就行了。
IBS =-lm -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lgdk_pixbuf-2.0 –lpangocairo -1.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0 -lglib-2.0 –lpthread
重新编译,make 回车,看问题是否解决,成功解决后直接make install回车。