下面是我在自己动手写操作系统的过程中遇到的一些问题,我发现书上并没有直接提到它们, 但是它们真的很重要,尤其是对于像我这样刚接触这方面的新手来说。我把它们整理成Q&A的形式供 大家参考。当然,以下均为鄙人拙见,有不妥之处还望达人指点。:-P

Q&A on OS Development


编者:王聪

Q:写操作系统一定要用C语言吗?
A:不一定!C语言只是挺适合用来写操作系统罢了。如果你行,完全可以使用C++或Pascal。Java之所以不行是因为 Java程序都是在Java虚拟机上执行的。

Q:为什么C语言适合写操作系统?
A:因为C语言既有高级语言的特性,也涉及很多底层的东西,尤其是它的可移植性非常好,所以 目前很多操作系统,比如Linux,Windows,Unix,Minix都是用C来写的。

Q:为什么编写操作系统还用重写一套C库函数?(假设你使用C语言)
A:因为如果你不写的话,你的操作系统将倚赖你使用的操作系统带的链接器和函数库,无法脱离现有操作系统运行。

Q:在什么时候使用高级语言?
A:任何时候,只要你认为高级语言能够完成你的任务!使用高级语言是为了方便和可移植性。

Q:怎么引导操作系统?
A:很简单。一开机时,BIOS会自动做一些工作,你所要做的是接着做,记得要把这段程序编译后放到 BIOS读取的地方。不要以为刚开机时很多功能都不能用,相反,通过中断你可以使用很多功能, 比如:显示彩色字符串,读取硬盘内容,得到CPU,显卡信息等。

Q:写操作系统应该搭建什么样的平台?
A:很多人喜欢用Windows + DOS + Linux + Virtual PC的组合,其实没有必要这么麻烦。我本人不用Window$,更不会用DO$, 我搭建的Linux + Bochs的平台完全足够了!其实他们用DOS的理由是它运行在实模式下,而Linux工作在保护模式下。 选用Linux是因为它带的工具强大。其实这太麻烦了,因为我们可以直接在Bochs里运行实模式下的代码,而且这些代码很少,如果你的操作系统要 在保护模式下工作的话。

Q:怎么实现GUI界面?
A:GUI很复杂,这方面的资料不多。我建议你使用现有的GUI库,比如X(听说还有个Y)。如果你想自己 写一个GUI,计算机图形学相关知识是必需的。

Q:内存0x00000~0x003ff是中断向量表,为什么Linux把它覆盖了?
A:因为Linux已经准备好了自己的中断调用,它对Linux来说已经没用了,可以安全地覆盖了。

Q:一开机时内存是怎么分配的?
A:看看下面的图,一目了然。

Q:为什么写bootsect时还要涉及FAT12格式?
A:那是因为你把你的软盘做成了FAT12格式,之所以要做成这种格式是因为让软盘里的文件可见,放置方便 。这样做的代价是你必须遵守FAT12的“规则”。我们当然可以把bootsect放到第一扇区,把loader 放到第2~4扇区,这样我们读取方便,但是它们将会不可见,而且放置不是那么方便。选择什么完全在你自己。

Q:那为什么写loader时还要涉及pe/elf文件格式?
A:因为你的loader要加载的kernel是pe/elf格式的,如果你怕麻烦,你可以把它做成纯二进制 文件,那就可以直接加载了。

Q:怎么理解Intel Pentium分页机制?
A:我个人认为最好的解释不在Intel的官方手册中,而在Andrew S. Tanenbaum写的《现代操作系统》一书中, 见第4.8.3节。

Q:怎么用GRUB Bootloader来引导我的系统?(假设你把系统放在软盘上)
A:(这个解答是翻译来的,原文出处实在搞不清楚了。)GRUB是在GPL下发行的。
GRUB主页:      http://www.gnu.org/software/grub
GRUB二进制文件:       ftp://alpha.gnu.org/gnu/grub/grub-0.90-i386-pc.tar.gz
GRUB源代码:    ftp://alpha.gnu.org/gnu/grub/grub-0.90.tar.gz
HOW-TOs:        http://www.washingdishes.freeuk.com/grubtut.html
                http://www.execpc.com/~geezer/osd/boot/grub-how.txt

1.你要准备的东西:
两张1.44M的软盘:其中一张「为了叙述方便,把它叫做软盘a」格式化成GRUB可以识别的格式,比如FAT12或ext2。另一张 软盘「把它叫做软盘b」如果有文件系统,文件系统将被破坏。
GRUB的二进制文件:stage1和stage2两个文件。
menu.lst文件:GRUB的配置文件。

2.在软盘a上建立一个目录/boot/grub,把stage1,stage2和menu.lst拷贝到这个目录下。

3.把stage1和stage2两个文件合并到一个二进制文件boot中:

(DOS/Windows):  copy /b stage1 + stage2 boot
      (Linux):        cat stage1 stage2 >boot

4.把boot文件直接写到软盘b中,这是扇区级别的,原有的文件系统将会被破坏。

(DOS/Windows):  partcopy boot 0 168000 -f0
   (Linux):        cat boot >/dev/fd0
PARTCOPY将会产生错误信息,因为boot远小于0x16800字节,这没有关系。

5.从软盘b启动计算机。

6.GRUB启动以后,拿出软盘b,插入软盘a。键入:setup (fd0)

7.现在软盘a可以引导了。不要移动,修改或者删除这张软盘上的"/boot/grub/stage2"文件!


Q:Intel定义了很多硬件结构,是不是都要用上?
A:其实没必要。很多结构可以不用,比如:DPL有4个级别,而Linux内核只使用了0和3这两个级别,而且Linux 内核也并没有为每个进程都分配LDT。当然了,有一些是必须要用的,比如:GDT,而其它一些的使用与否取决于你的设计目的。 PS:虽然Intel相当成功地完成了向前兼容和新的性能,但是Intel构架并不是那么优秀。

Q:页和页帧有什么不同?
A:页帧(page frame)代表一块内存地址空间,它的大小和页一样,而页(page)代表一个特定大小的数据块, 它可以被放在内存的页帧中,也可以放在硬盘上。

Q:很多关于操作系统的书都是讲理论方面的,有没有介绍具体怎么实现的?
A:有!首先推荐的是Andrew S. Tanenbaum和Albert S. Woodhull写的 《操作系统:设计与实现》,它也是Linus当年读的书,介绍了如何实现Minix,附带了 Minix的源代码,就是没有告诉你bootsect和makefile怎么写。 Marshall Kirk McKusick等著的《The Design and Implementation of the 4.4BSD Unix Operating System》介绍了BSD的实现。 国内还有两本不错的书,一本是 《自己动手写操作系统》,于渊著,电子工业出版社出版,以开发Tinix为例讲解如何写一个操作系统; 另一本是《Linux内核代码完全注释》,赵炯著,机械工业出版社出版,对Linux 0.11内核 代码进行了很好的解释。

Q:听说很少有人做操作系统,可以参考的代码只有Linux吗?
A:不是!其实开源的操作系统内核并不是那么少。
React OS是一个模仿Windows的开放的操作系统。
GeekOS是一个供你参考的小型操作系统。
Minirighi是一个多线程的开源操作系统,是教学用的。
早期的Unix代码也是可以得到的,不过听说它很geeky!BSD当然也是开放的,但是它 太庞大了。
Minix是Andrew S. Tanenbaum教授写的为教学之用的类Unix系统,可惜它的代码只能在《操作系统:设计与实现》 一书中得到,并不是免费的。

Q:介绍Linux内核的资料都有哪些?
A:上面提到的《Linux内核代码完全注释》一书不错。当然还有很多其它,像: 潘晓雷写的《Linux0.11源码分析》一文,袁镱写的《Linux0.11 下的内存管理》一文 也挺不错。 关于更高版本的Linux内核,推荐Daniel P. Bovet和Marco Cesati合著的《Understanding the Linux Kernel, 2nd Edtion》 或国内的《Linux内核源代码情景分析》(Linux Kernel 2.4)。David A Rusling写的《Linux Kernel》和 Tigran Aivazian写的《Linux Kernel Internals》同样不错, Robert Love的《Linux Kernel Development, Second Edition》也值得去读。 Mel Gorman的《Understanding the Linux Virtual Memory Manager》对Linux内存管理做了 更深入的介绍。

Q:介绍操作系统理论的优秀图书都有哪些?
A:OK!我已经把这整理出来了,看这里

Q:我想写一个操作系统内核,你能给我点儿建议吗?
A:可以。首先一定要明确你的设计目标,明确你到底想要一个什么样的系统时再开始动手。然后,分清哪些工作是由软件 (内核)来完成的,哪些是由硬件来完成的,记住,这一点很重要。最后,要有足够的耐心,编写内核并不像编写 其它程序那样很容易debug,内核的很多bug很难修改甚至捕捉,而这需要设计者有足够的细心和耐心。祝你好运!