MIT6.828学习之homework10:bigger files for xv6

在这个作业中,您将增加xv6文件的最大大小。目前,xv6文件被限制在140个扇区,即71,680字节。这个限制来自于一个xv6 inode包含12个“直接”块号("direct" block number)和一个“单间接”块号("singly-indirect" block number),这个块号指的是一个最多可以容纳128个块号的块,总数为12+128=140。您将更改xv6文件系统代码,使每个inode中支持“双间接”块("doubly-indirect" block),其中包含128个单间接块地址,每个单间接块最多可以包含128个数据块地址。其结果是,一个文件将能够由最多16523个扇区(或大约8.5 mb)组成:11+128+128*128=16523

Preliminaries(预设)

修改您的Makefile的cpu定义,使其如下:

CPUS := 1

Add

QEMUEXTRA = -snapshot

right before QEMUOPTS

当xv6创建大文件时,上述两个步骤极大地加快了qemu的速度。

mkfs初始化文件系统,使其拥有少于1000个空闲数据块,这太少了,无法显示将要进行的更改。修改 param.h ,将FSSIZE设置为:

#define FSSIZE       20000  // size of file system in blocks

将big.c下载到xv6目录中,将其添加到UPROGS列表中,启动xv6并运行big。它创建一个xv6允许的最大文件,并报告结果大小。现在应该还是140个扇区。

What to Look At

磁盘上inode的格式由fs.h中的struct dinode定义。对NDIRECT、NINDIRECT、MAXFILE和struct dinode的addrs[]字段要感兴趣。这是xv6标准inode的结构图:
在这里插入图片描述
在磁盘上查找文件数据的代码位于fs.c中的bmap()中。看看它,确保你明白它在做什么。在读取和写入文件时都调用bmap()。当写文件的时候,bmap()根据保存文件内容的需要分配新块,如果需要保存块地址,则分配一个间接块。

bmap()处理两种类型的块号。bn参数是一个“逻辑块”( "logical block")——一个相对于文件开头的块号。ip->addrs[]中的块号和bread()的参数都是磁盘块号。您可以将bmap()视为将文件的逻辑块号映射到磁盘块号。

Your Job

修改bmap(),使它除了直接块和单间接块之外,还实现了一个双间接块。你必须只有11个直接块,而不是12个,来为你新的双间接块腾出空间;不允许更改磁盘inode的大小。ip->addrs[]的前11个元素应该是直接块;第12个应该是一个单独的间接块(就像当前的块);13号应该是你新的双间接块。

您不需要修改xv6来处理具有双间接块的文件的删除。

如果一切顺利,big将会报告它可以读写16523个板块。这将需要几十秒的时间来完成。

Hints

确保您理解bmap()。写出ip->addrs[]和它所指向的the indirect block, the doubly-indirect block and the singly-indirect blocks以及数据块之间的关系图。确保您理解了为什么添加一个双间接块会将最大文件大小增加了16,384块(实际上是16383,因为必须将直接块的数量减少1)。

考虑如何用逻辑块号索引双间接块及其指向的间接块。

如果更改NDIRECT的定义,您可能必须更改file.h中的struct inode中的addrs[]的大小。确保struct inodestruct dinode的addrs[]数组中有相同数量的元素

如果更改NDIRECT的定义,请确保创建一个新的fs.img,。因为mkfs也使用NDIRECT来构建初始文件系统。如果删除 fs.img,Unix的 make指令(不是xv6)将为您构建一个新的。

如果您的文件系统进入一个坏的状态,可能是由于崩溃(by crashing),删除fs.img(在Unix中执行,而不是xv6)。make将为您构建一个新的干净的文件系统映像。

不要忘记brelse()bread()的每一个块

您应该只根据需要分配间接块和双间接块,就像原始的bmap()一样。

代码

这个地方,代码很简单,其他东西都看不懂也能完成这部分代码。只需要看懂上面inode的结构图,然后知道是要把12+128改成11+128+128*128就可以完成:

static uint
bmap(struct inode *ip, uint bn)
{
  uint addr, *a;
  struct buf *bp,*dp;

  if(bn < NDIRECT){
    if((addr = ip->addrs[bn]) == 0)
      ip->addrs[bn] = addr = balloc(ip->dev);
    return addr;
  }
  bn -= NDIRECT;

  if(bn < NINDIRECT){
    // Load indirect block, allocating if necessary.
    if((addr = ip->addrs[NDIRECT]) == 0)
      ip->addrs[NDIRECT] = addr = balloc(ip->dev);//Allocate a zeroed disk block.
    bp = bread(ip->dev, addr);
    a = (uint*)bp->data;
    if((addr = a[bn]) == 0){
      a[bn] = addr = balloc(ip->dev);
      log_write(bp);
    }
    brelse(bp);
    return addr;
  }
  bn -= NINDIRECT;

  if(bn < MAXFILE-NINDIRECT-NDIRECT){
    // Load indirect block, allocating if necessary.
    if((addr = ip->addrs[NDIRECT+1]) == 0)
      ip->addrs[NDIRECT+1] = addr = balloc(ip->dev);//Allocate a zeroed disk block.
    bp = bread(ip->dev, addr);
    a = (uint*)bp->data;
    if((addr = a[bn/NINDIRECT]) == 0){
      a[bn/NINDIRECT] = addr = balloc(ip->dev);
      log_write(bp);
    }
	dp=bread(ip->dev, addr);
	a = (uint*)dp->data;
	if((addr = a[bn%NINDIRECT]) == 0){
      a[bn%NINDIRECT] = addr = balloc(ip->dev);
      log_write(dp);
    }
	brelse(dp);
    brelse(bp);
    return addr;
  }

  panic("bmap: out of range");
}

其他修改

// file.h struct inode
uint addrs[NDIRECT+2];

// fs.h struct dinode
uint addrs[NDIRECT+2];

// fs.h
#define NDIRECT 11
//sizeof(uint)=4, NINDIRECT=128
#define NINDIRECT (BSIZE / sizeof(uint))  
#define MAXFILE (NDIRECT + NINDIRECT*129)


结果:
在这里插入图片描述
但是这样毕竟不好,我们还是来看看struct inode以及big具体在做什么

// in-memory copy of an inode
struct inode {
  uint dev;           // Device number ??什么设备
  uint inum;          // Inode number
  int ref;            // Reference count
  struct sleeplock lock; // protects everything below here
  int valid;          // inode has been read from disk?

  short type;         // copy of disk inode
  short major;
  short minor;
  short nlink;
  uint size;
  uint addrs[NDIRECT+2];
};

big就向big.file不停的写入buf,每个buf大小刚好是一个块大小,内容是n(n为第n个buf);写完之后又从里面不停的读出buf,每个buf大小刚好是一个块大小,并验证内容是否是n。

还是不明白这里的dev指什么,也没有找到big.c中的big.file在哪里,为什么可以通过往big.file中写入失败而知道最大扇区是16523?

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值