austgl / writeos

Automatically exported from code.google.com/p/writeos
0 stars 0 forks source link

一些建议,部分是结构性的,也许现在还来得及 #11

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
1、目前叙述Loader的部分篇幅过大。其实,这部分代码是完全�
��必要的。因为
Grub/LILO/Syslinux等优秀的Loader已经存在,我们没有必要重新发��
�轮子。

我们需要的,是让代码兼容于Linux内核,使得Loader能够识别并
加载我们的操作系
统。为此,需要向读者介绍Linux Boot 
Protocol。这方面,我已经做了一些研究,已
经有简化的代码片段可以编写一个最小的(1K字节)的内核,
完全兼容Grub/LILO
/SysLinux,甚至可以用Qemu直接载入。

2、软盘镜像有点过时了,而且需要用不完全自由的FAT格式(�
��知道微软什么时候会
发神经收专利费,尽管现在大家都在用)。我写的一个Project�
��成的是完全开放的
iso镜像,同样可以让虚拟机直接加载,并显得更专业。iso镜��
�使用isolinux启动,
从而避免自行编写复杂的cdrom启动代码(再次强调,我们要写
的是OS,不是OS
Loader,不要喧宾夺主)。

3、VirtualBox尽管有好用的图形界面,但有一点比不上Qemu,就��
�不支持内核的直接
载入。在这方面Qemu非常好,直接qemu -hda /dev/zero -kernel 
myos就可以加载内
核镜像。这真是太方便了,甚至可以写到Makefile里面,直接mak
e qemu就能完成编译
并加载到qemu测试。
4、我觉得,应该向读者介绍更多的自由软件开发常规。例如A
utoconf/Automake等,
并适当引入SVN版本管理。编写OS毕竟不是小工程,应该从一开
始就有正确的管理,因
此这些技术都是必须要用到的。

我打算用邮件向你提交本人的示例代码。

Original issue reported on code.google.com by earthengine on 16 Oct 2008 at 10:36

GoogleCodeExporter commented 9 years ago
> New issue report by earthengine:
> 
1、目前叙述Loader的部分篇幅过大。其实,这部分代码是完全�
��必要的。因为
> 
Grub/LILO/Syslinux等优秀的Loader已经存在,我们没有必要重新发��
�轮子。
> 
> 
我们需要的,是让代码兼容于Linux内核,使得Loader能够识别并
加载我们的操作系
> 统。为此,需要向读者介绍Linux Boot 
Protocol。这方面,我已经做了一些研究,已
> 
经有简化的代码片段可以编写一个最小的(1K字节)的内核,
完全兼容Grub/LILO
> /SysLinux,甚至可以用Qemu直接载入。

事实上,我原来的思路是从 0 
开始,而且我没有打算写一个大而全的 OS,因为我们
有了 Linux,读者如果有能力去了解 
Linux,就不用来看本书。现在的操作系统教材
往往是从抽象层面讲 
OS,而不是切切实实地讲到每一个细节。如果按照你的思想来
说,
《现代操作系统》这本书就足够了,而我这本书的初衷和它��
�然是不一样的,也不会去
试图覆盖《现代操作系统》的一些东西。

> 
2、软盘镜像有点过时了,而且需要用不完全自由的FAT格式(�
��知道微软什么时候会
> 
发神经收专利费,尽管现在大家都在用)。我写的一个Project�
��成的是完全开放的
> 
iso镜像,同样可以让虚拟机直接加载,并显得更专业。iso镜��
�使用isolinux启动,
> 
从而避免自行编写复杂的cdrom启动代码(再次强调,我们要写
的是OS,不是OS
> Loader,不要喧宾夺主)。

这方面我承认,囿于知识的贫乏,我没能去使用 ISO 
镜像。对于您的最后意见,我还是
不太同意,我希望这本书尽量地覆盖一些底层的细节,因为��
�些细节往往是那些讲解操作
系统的书所忽略的,读者很难从别的地方找到。

> 
3、VirtualBox尽管有好用的图形界面,但有一点比不上Qemu,就��
�不支持内核的直接
> 载入。在这方面Qemu非常好,直接qemu -hda /dev/zero -kernel 
myos就可以加载内
> 
核镜像。这真是太方便了,甚至可以写到Makefile里面,直接mak
e qemu就能完成编译
> 并加载到qemu测试。

同样是知识所限,我当时没有选择 
Qemu。至于虚拟机,其实我觉得选择哪个都无所谓,每个
软件总有自己的长处和短处,比如 Bochs 
支持系统级的调试,也是它的一大优点,读者其实
是可以自由选择的。

> 
4、我觉得,应该向读者介绍更多的自由软件开发常规。例如A
utoconf/Automake等,
> 
并适当引入SVN版本管理。编写OS毕竟不是小工程,应该从一开
始就有正确的管理,因
> 此这些技术都是必须要用到的。

事实上,我打算写的是一本书,而不是一个操作系统,那个��
�作系统的代码完全是为书服务
的,所以这个操作系统不可能很大,这样会使读者望而生畏��
�像现在的 Linux 代码那样。
等这本书结束的时候,这个操作系统也不大可能是一个实用��
�操作系统,所以这些复杂的
工具大概不会用到。

从您的意见来看,我感觉我们两个最大的不同是对这个操作��
�统作用的理解。您是希望这个
操作系统成为一个能持续发展,不断完善的实用操作系统,��
�这本书成为一个注脚;我是
希望这个操作系统保持尽量的简洁,为书中所介绍的知识服��
�,当读者读完这本书时,只会
拿到一个实验性质的几乎无用的 
OS,但是他所积累的知识会有助于他去理解 Linux/Minix
这样一些复杂的操作系统。

以上是我的意见,欢迎拍砖!

Original comment by solrex on 16 Oct 2008 at 10:57

GoogleCodeExporter commented 9 years ago
我设想以此节取代原2.2 FAT的介绍

2.2 Linux 启动协议
       上一节,我们介绍了如何编写引导扇区并将它写入引导软盘的合适位置,以便我们的代码
能够被BIOS加载。无疑这是编写真正操作系统的第一步,但是�
��们必须明白,即使是这一步也不
是那么简单的。从软盘引导也许是最简单的了,但实际应用��
�时候,我们的操作系统必须能够从
各种不同的介质加载:从硬盘,从光驱,从老式的ZIP驱动器��
�从USB外置硬盘,从U盘……要是一一
编写启动代码,这无疑有相当的工作量。
      幸好,不需要重新发明轮子!我们有各种各样的“引导加载器”可以用来加载引导代码。例
如,如果你用过任何眼下流行的Linux发行版,你多半是用Grub��
�载系统的。如果你用过Linux
Live 
CD,那么你也许知道有个isolinux可以引导光盘上的Linux。如果��
�用Linux多年,知道一些
掌故,那么你也会知道以前的Linux发行版用LILO来引导系统。��
�要注意的是这些引导加载器不一
定只能加载Linux,例如很多发行版都提供一个内存检测工具mem
test86,这个并不是Linux,但同
样可以被加载器加载。
      所以,我们不需要过多了解引导加载器如何识别各种各样的启动环境。但是有一个问题仍
然必须解决:必须让引导加载器能够识别我们的“操作系统��
�代码。这样,就需要了解Linux启动协
议,因为所有兼容Linux的引导加载器必须和这个协议兼容,所
以只要我们遵守了这套协议,就能
让Linux识别我们的引导加载器。

下面,我们从样板代码开始,看看符合Linux启动协议的“内核
”应该具有什么样的结构。

start:

            jmp .

.org 497

setup_sects:        .byte   _setup_sects

root_flags:     .2byte  1

syssize:        .4byte  _file_length

ram_size:       .2byte  0

vid_mode:       .2byte  0xffff

root_dev:       .2byte  0

boot_fliag:     .2byte  0xaa55

.text

.code16

            jmp OS_START

header_magic:       .ascii  "HdrS"

version:        .2byte  0x200

realmode_swtch:     .4byte  0

start_sys:      .2byte  0

kernel_version:     .2byte  0

type_of_loader:     .byte   0

loadflags:      .byte   0

setup_move_size:    .2byte  0

code32_start:       .4byte  0

ramdisk_image:      .4byte  0

ramdisk_size:       .4byte  0

bootsect_kludge:    .4byte  0

head_end_ptr:       .2byte  0

            .2byte  0

cmd_line_ptr:       .4byte  0

initrd_addr_max:    .4byte  0

kernel_alignment:   .4byte  0

relocatable_kernel: .byte   0

            .2byte  0

            .byte   0

cmdline_size:       .4byte  0

hardware_subarch:   .4byte  0

hardware_subarch_data:  .8byte  0

OS_START:

/*Start point, default address is 9020:0000,but it is not compatible with the 
la*/

            ljmp    $0x9000,$prog_start

历史上,Linux内核是可以直接拷贝到软盘从引导扇区开始的位
置上,然后从该软盘启动的。但是
新版本的内核已经不再支持这种方式。但是作为历史遗留问��
�,内核的第一个扇区总是留给引导
扇区。而引导扇区需要带有一个引导程序。在这里,为了简��
�代码,简单地用一个死循环开始。

引导扇区中间的部分是什么都不重要,因此接下来的org 
497是要跳过中间的字节,直接跳到第
497个字节去。在这里,正确设置setup_sects和syssize这两个字段��
�常重要。前者是内核的“初
始化代码”所占用的扇区数目,而后者是整个内核的大小(��
�须为512的整数倍)。其余字段都有
相对固定的值,目前你只要按照上面的方式赋值即可。

但是计算syssize和setup_sects并不简单。因为内核的大小会随着��
�们程序开发的进度变化,如
果每次编译都要回头手工设置这两个值,那也太麻烦了。幸��
�,连接脚本可以为我们做到这个:
SECTIONS

{

    . = 0;

    .bs :

    {

    } = 0

    . = 512;

    .text :

    {

        _ftext = .;

    } = 0

    .end :

    {

        . = ALIGN(512);

    }

    _file_length = ALIGN(512);

    _setup_sects = ALIGN(512) / 512 -1;

}
上面这个连接脚本指出:连接程序会遇到3个不同的段,分别�
��名为.bs,.text和.end。在加载
了.bs段后,要把当前位置设置到512。所以.bs段的大小就正好��
�512,而不管它实际上可能占不
满。在.text段之后的.end段,要把当前位置对齐到512字节,这��
�,.text段的长度就总是512字
节的整数倍。最后,我们要求连接程序计算两个变量的值。��
�两个变量的值在汇编代码里面是声
明为extern的,汇编器生成的目标代码中这里是空位。这样,��
�接程序在分析了连接脚本之后,
首先就会生成一个布局,然后把计算出来的变量值填充到空��
�里。这样就完成了设置这些关键变量。

现在,我们来看看内核是如何加载到内存的。启动协议规定��
�载点是0x9000:0000。但是要注意的
是,这个位置是引导扇区和所有setup_sects加载到的位置。引导
加载程序会跳过引导扇区,因此
实际的加载点是0x9020:0000。但是这里有一个问题,就是在代码
里面的标号和字符串地址等的值
是加上了512的,并不是从0开始。所以,我们需要一段设置段�
��存器的代码,用来标准化段的引
用,使得此后对地址的引用能够正确。
OS_START:

/*Reset the CS,DS,ES & SS, Set SP to $1000*/

            ljmp    $0x9000,$prog_start

prog_start:

            mov     %cs,%ax

            mov %ax,%ds

            mov %ax,%es

            mov %ax,%ss

            mov $0x1000,%sp

我们首先执行一个段间跳转,使CS段寄存器固定为0x9000,这样
所有的标号都有了正确的偏移
量。此后,我们把CS的值传到其它段寄存器。最后,设置一下
堆栈指针。

Original comment by earthengine on 16 Oct 2008 at 2:16

GoogleCodeExporter commented 9 years ago
我同意solrex的看法。
作为一个能发展的操作系统,需要的东西实在太多了。
最低限度,一个能发展的操作系统至少要有一个编译器吧。��
�里就会耗掉至少10w行代码。
文字编辑器呢,好像也是必须要的,不可能为了用vim或者emacs
还需要切到linux写代码吧。
然后shell、更强壮的文件系统、多处理器支持、更强壮的内存
管理、甚至在这个年代必需一从头
就考虑的64位机。
--到时候会发现所有的东西都缺。难道要把这些全从linux迁移�
��去?

就像侯捷先生在深入浅出MFC里面那样,做一个无用的操作系��
�。
但读者学到的东西确实是有用的。
ps.如果这个操作系统还没有名字的话,我建议取做μOS(/mu OS)

Original comment by yegong1...@gmail.com on 7 Nov 2008 at 8:09