我要开动了!
いただきます!
Last updated
Was this helpful?
いただきます!
Last updated
Was this helpful?
上一节中你已经大概了解了 EOS 究竟是如何被编译的, 甚至已经自己实现了用于构建 EOS 的 Makefile. 虽然, 在理解原理的基础上, 直接复制使用教程中提供的 Makefile 也没什么不妥.
但是聪明的你再一次发现: 我们在上一节中构建得到的 EOS 引导程序和内核是无法直接被虚拟机启动的. 你应该还记得, 在本章的第一节中, 你已经使用 QEMU 和 Bochs 分别启动了 EOS, 那时你使用的是一个名为 floppy.img
的软盘镜像.
本节中我们将研究如何生成这个可以用来引导 EOS 的软盘镜像.
如果你曾经阅读过其他的一些简易操作系统的源代码, 或者相关的书籍 (“30 天自制操作系统”, “Orange‘S” 等), 你会发现在许多 toy OS 的实现中, 作者都不约而同的选择了软盘这一介质作为系统的载体. 因为软驱相对于其他设备来说更好控制, 尤其是在引导程序大小限定在一个扇区内 (512 字节) 的时候.
事实上, 自行实现操作系统的引导程序往往是一个费力不讨好的活计. 于是在更多的 toy OS 中, 人们选择利用现成的工具进行引导 (例如 ); 在现实世界中, 操作系统也大多依赖 引导, 而非传统的 .
那么当一个软盘插入计算机, 用户按下开机键以后, BIOS 是如何知道要从这个软盘启动操作系统的呢? BIOS 会首先检查软盘的第一个扇区, 如果其最后两个字节分别是 0x55
, 0xaa
, 则 BIOS 就知道: 这个软盘的第一个扇区中存放了引导程序, 应当将这个扇区加载到内存的指定位置 (0x7c00
) 并执行. 之后的事情就由存储在软盘第一个扇区内的程序负责了.
在 EOS 中, boot.bin
就是那个存储在第一个扇区内的, 最初的引导程序. 除了这个文件会直接被写入软盘扇区, 其余的两个文件 loader.bin
和 kernel.dll
则会以文件的形式, 存入软盘上的 FAT12 文件系统中. 至于 libkernel.a
, 如果你还有印象的话, 这个文件是给用户应用程序用的, 暂时和 EOS 的软盘镜像无关.
在目前的 OS lab 环境当中, 我们可以使用 dd
命令来创建一个空的软盘镜像. 在此之前你需要先执行 make
, 确保 build
目录中已经生成了 EOS 相关的文件:
这两条命令完成的操作也很简单. dd
命令会按照用户指定的选项, 将输入拷贝到输出. 第一条命令实际上就是将输入文件 (if
) build/boot.bin
直接拷贝到了输出文件 (of
) build/floppy.img
中, 指定单次拷贝 512 字节 (一个扇区的大小), 拷贝 1 次.
第二条命令的作用是把软盘镜像的剩余部分用 0x00
填满. 因为 3.5 英寸软盘的容量是 1440 KB (1.44 MB), 按照一个扇区 512 字节来算, 刚好 2880 个扇区. 因为我们已经用 build/boot.bin
填充了第一个扇区, 所以这次要跳过 1 个扇区把剩下的 2879 个扇区填满. 这样, 我们最后就得到了一个空的软盘镜像. 不要担心这个镜像不会被系统识别, 因为在其第一个扇区中已经包括了 FAT12 文件系统的一些关键信息了.
之后要怎么办呢? GNU/Linux 中有一对命令叫做 mount
和 umount
: 前者可以把刚才的软盘镜像作为文件系统, 挂载到某个实际的目录中去; 后者可以卸载之前已经执行过挂载操作的目录. 你现在可能会觉得一头雾水, 没关系我们先来试一下:
这条带选项的 mount
命令需要特权, 聪明的你知道应该怎么做. 我们首先建立了一个临时目录 /tmp/floppy
, 然后执行了 mount
, 将软盘镜像挂载到了新建的目录下. 这时, 任何访问 /tmp/floppy
的操作都会被映射到软盘镜像内的 FAT12 文件系统中去. 也就是说, 我们可以直接把另外两个文件复制到这个目录:
看起来这些文件只是被复制到了目录内, 实际上并没有, 他们直接被写入到软盘镜像里去了. 这个时候我们可以卸载这个镜像:
此时 /tmp/floppy
就变回了正常的目录, 不再和软盘镜像建立联系, 不信你用 ls
命令看一下其中的内容. 至此, 软盘镜像就制作完成了, 好像也挺简单的嘛, 接下来启动试试:
等等... 这是什么情况?
好吧, 看来用 dd
和 mount
来制作软盘镜像这条路行不通. 我们假装一切都没有发生过...
败者食尘!
将 imgedit
的源码 (src
目录) 放入 eos/util/imgedit
目录中. 为了将其编译为可执行文件, 我们同时在目录内建立一个 Makefile. 目前的 eos
目录结构如下:
编辑 eos/util/imgedit/Makefile
, 写入以下内容:
你可以直接在 imgedit
目录执行 make
, 当然也可以这样:
之后你可以直接用 util/imgedit/build/imgedit
来生成软盘镜像 (路径好长):
这次就可以正常通过软盘镜像启动 EOS 了.
由于我们已经可以完整构建 EOS 内核, 并生成最终的可引导镜像, 我们可以更新一下之前 eos
目录中的那个 Makefile, 实现一键构建+启动 EOS:
此时如果想一键构建+启动, 只需要:
如果你需要用 QEMU 来启动, 可以:
现在我们已经可以实现 EOS 的构建了, 那么如何才能得到一个可以启动的软盘镜像呢? 教程作者为你实现了一个简单的工具, 它可以生成和编辑 FAT12 文件系统的软盘镜像的内容: 这个工具叫做 imgedit
, 使用 C++11 编写, 可以.
写这样一个工具类的小软件并不复杂, 你只需要参考 FAT12 的 , 或者一些即可. 完成后你可以使用一些现成的 FAT12 镜像来对你的程序进行测试, 或者使用刚刚的 dd
+mount
创建一系列用于测试的镜像.