XV6

该工具是运行于 Linux 环境中的,为 xv6 系统生成磁盘文件系统的影像。其输入是可运行于 xv6 的多个应用程序。实现代码在 mkfs.c,其中 mkfs.c#L20 给出了 xv6 磁盘文件系统的布局。

xv6 有两个磁盘,分别是 xv6.img,和 fs.img,其中 fs.img 用于文件系统,而 xv6.img 用于装载引导程序和系统内核。

xv6.img 布局如下:

boot block kernel
第 0 块 从 1 开始

Makefile 中,fs.img 的生成如下:

fs.img: mkfs README.md $(UPROGS)
  ./mkfs fs.img README.md $(UPROGS)

也就是说,文件系统是由 mkfs 程序生成的,包括布局、数据载入。文件系统的布局如下:

名字 引导块 超级块 日志区 索引节点区 位图区 数据区
大小 1 1 nlog ninodeblocks nbitmap FSSIZE-nmeta

引导块占用第 0 号物理块,不属于文件系统管辖,如果系统中有多个文件系统,只有根文件系统才有引导程序放在引导块中,其余文件系统都不使用引导块。

超级块占用第 1 号物理块,是文件系统的控制块。超级块包括:文件系统的大小、空闲块数目、空闲块索引表、空闲 i 节点数目、空闲 i 节点索引表、封锁标记等。超级块是系统为文件分配存储空间、回收存储空间的依据。

在 xv6 中,引导块没有作用。

1. 添加交换区

为了给之后的交换功能做准备,我们对 fs.img 的生成进行相应的改造,在数据区后面添加一个交换区。交换区是独立于文件系统之外的一个区域。

首先我们要对 fs.img 进行相应的扩张,fs.img 默认大小为 512000,也就是 1000 个 512 字节大小的盘块。我们扩展 fs.img 为 1024000 字节,后面的 512000 作为交换区。

  1. param.h 的最后添加一行

    #define SFSIZE 1000   // size of swap file in blocks
    
  2. mkfs.c#L110 的循环中,i 的终止条件改为 i < FSSIZE + SFSIZE

  3. Makefile#L185fs.img 的生成添加一行

    fs.img: mkfs README.md $(UPROGS)
      ./mkfs fs.img README.md $(UPROGS)
      dd if=README.md of=fs.img seek=1000 conv=notrunc
    
  4. ide.c#L78 中盘块号的范围改为

    if(b->blockno >= FSSIZE + SFSIZE)
    

此时,交换区的添加算是完成了。

2. 读写交换区

  1. xv6 已经提供了读超级块的函数,我们将其改造为读交换区的系统调用,就可以完成交换区的读取。
  2. xv6 已经提供了对盘块清零的函数,我们将其改造为写交换区的系统调用,就可以完成交换区的写入。注意,交换区的使用只涉及缓存层,所以我们不用 log_write() 而直接使用 bwrite()