在内核启动之后,需要有文件系统保存程序和数据,例如 shell
中所执行的外部指令:ls
、mkdir
、rm
、cp
等程序,以及用户所需的其他数据文件等。由于我们将 XV6 运行于 QEMU 仿真环境,因此需要把相应的文件系统内容形成磁盘镜像文件。
XV6 中有两个磁盘镜像,一个是 xv6.img
,用于存放 XV6 操作系统;另一个是 fs.img
,作为磁盘文件系统的镜像。当使用 QEMU 仿真器运行 XV6 时,将使用上述两个镜像。Makefile
中定义了 QEMUOPTS
变量,用作 QEMU 仿真参数,其中使用 -driver
选项定义了两个磁盘驱动器:
QEMUOPTS = -drive file=fs.img,index=1,media=disk,format=raw -drive file=xv6.img,index=0,media=disk,format=raw -smp $(CPUS) -m 512 $(QEMUEXTRA)
xv6.img
,格式为 raw-smp
fs.img
,格式为 raw
QEMUOPTS
中的 QEMUEXTRA
暂时没有定义,根据名字可知:读者可以根据自己的需要扩充其他额外的选项。
XV6 有三种启动方式,在 Makefile
中相关的代码如下:
qemu: fs.img xv6.img
$(QEMU) -serial mon:stdio $(QEMUOPTS)
qemu-memfs: xv6memfs.img
$(QEMU) -drive file=xv6memfs.img,index=0,media=disk,format=raw -smp $(CPUS) -m 256
qemu-nox: fs.img xv6.img
$(QEMU) -nographic $(QEMUOPTS)
当使用 make qemu
启动系统时,会弹出一个新窗口。而 make qemu-nox
虽然还是使用上面的选项,但是多了一个 -nographic
选项,因此不会弹出额外的窗口,而是直接在现有终端下显示 XV6 的输出。make qemu-memfs
则是使用内存盘来保存整个文件系统。
这里用到了三个磁盘影像 xv6.img
、fs.img
、xv6memfs.img
。其中:
xv6.img
由 bootblock
和 kernel
构成。fs.img
由 README.md
和 $(UPROGS)
构成。xv6memfs.img
由 bootblock
和 kernelmemfs
构成。从 Makefile
有关 xv6.img
的生成规则看,xv6.img
依赖于启动扇区 bootblock
以及 kernel
。
xv6.img: bootblock kernel
dd if=/dev/zero of=xv6.img count=10000
dd if=bootblock of=xv6.img conv=notrunc
dd if=kernel of=xv6.img seek=1 conv=notrunc
磁盘镜像 fs.img
是通过 mkfs
工具完成的,相应的 Makefile
给规则如下:
fs.img: mkfs README.md $(UPROGS)
./mkfs fs.img README.md $(UPROGS)
也就是说 mkfs
将 README.md
和 $(UPROGS)
指定的那些文件创建出符合 XV6 文件系统格式的磁盘镜像。$(UPROGS)
给出的文件名对应于可以运行与 XV6 系统的可执行文件,我们会在学习了 XV6 的 $(OBJS)
内核主体代码之后,再来学习和分析这些 XV6 的应用程序。
我们用 du -sh -b fs.img
命令可知该磁盘文件系统的总容量为 512000 字节,相当于 1000 个 512 字节大小的盘块。
由于我们还没有学习 XV6 的文件系统格式,因此现在也无法分析 fs.img
的内容。之后我们会专门讨论 mkfs
工具的实现。
与 xv6.img
由启动扇区 bootblock
和内核 kernel
组成不同,xv6mem.img
还包含了完整的磁盘文件系统的内容(即 kernelmemfs
= kernel
+ fs.img
)。
xv6memfs.img: bootblock kernelmemfs
dd if=/dev/zero of=xv6memfs.img count=10000
dd if=bootblock of=xv6memfs.img conv=notrunc
dd if=kernelmemfs of=xv6memfs.img seek=1 conv=notrunc