XV6努力实现XV6操作系统三级间接时候崩溃 [英] XV6 crashes when trying to implement triple indirection in xv6 operating system

查看:346
本文介绍了XV6努力实现XV6操作系统三级间接时候崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

原来XV6-rev7的操作系统包括:结果
12块指示结果
1间接blcok(点128块)

这意味着我们有140块。结果
每个块的大小为512KB ==> 512 * 140 = 71,680〜= 70KB是XV6文件大小的限制。

我要implemet,以支持具有40MB大小的文件XV6三重间接访问。

为了做到这一点,我将需要实施前的三双间接间接。结果
所以我花了2块指示从12我有。结果
 1为双间接和另一个用于三重间接的。结果,
这是我现在所拥有的:结果
直销:10块结果
单间接:128结果
双间接:128 * 128结果
三重间接:4 * 128 * 128(我用4,而不是128,因为这是足以让40MB)

这就是为什么的#define NDIRECT 10 UINT addrs的[NDIRECT + 3];

文件的大小限制=(10 + 128 + 128 * 128 + 4 * 128 * 128)* 512KB = 42013696〜42MB =

所以,我理解这个概念。
fs.c 三重间接的实现是在文件中的函数 BMAP 。结果
这是它的外观:结果

有关某种原因,当我试图创建文件,8.5MB大小失败:
结果
我使用的Bochs模拟器

我也不能确定什么样的价值观,我需要在mkfs.c改变:

  INT的nblocks = 20985;
INT n日志= LOGSIZE;
INT ninodes = 200;
INT大小= 21029;

fs.h中:

  //磁盘上的文件系统格式。
//两个内核和用户程序中使用这个头文件。//块0是未使用的。
//块1超级块。
//块2到sb.ninodes / IPB持有的inode。
//控股sb.size位,然后无位块。
//然后sb.nblocks数据块。
//然后sb.nlog日志块。#定义ROOTINO 1 //根i编号
的#define BSIZE 512 //块大小//文件系统的超级块
结构超级{
  UINT大小; //文件系统的图像尺寸(块)
  UINT的nblocks; //数据块数
  UINT ninodes; // inode的数目。
  UINT n日志; //日志块的数量
};#定义NDIRECT 10
#定义NINDIRECT(BSIZE /的sizeof(UINT))
的#define MAXFILE(NDIRECT + NINDIRECT + NINDIRECT * NINDIRECT + 4 * NINDIRECT * NINDIRECT)//在磁盘inode结构
结构dinode {
  short类型; // 文件类型
  短期专业; //主设备号(仅T_DEV)
  短未成年人; //次设备号(仅T_DEV)
  短nlink; //连接数在文件系统inode
  UINT大小; //文件的大小(字节)
  UINT addrs的[NDIRECT + 3]; //数据块地址
};//每个块的inode。
IPB的#define(BSIZE /的sizeof(结构dinode))//阻止包含我的inode
的#define IBLOCK(ⅰ)((ⅰ)/ IPB + 2)的每块//位图位
#定义BPB(BSIZE * 8)对于B座//包含块位
#定义BBLOCK(B,ninodes)(B / BPB +(ninodes)/ IPB + 3)//指南是含有的dirent结构的序列的文件。
#定义DIRSIZ 14结构的dirent {
  USHORT INUM;
  焦炭名[DIRSIZ]
};

fs.c:

  //返回索引节点IP的第n个块的磁盘块地址。
//如果不存在这样的块,BMAP分配一个。
静态UINT
BMAP(结构的inode * IP,UINT BN)
{
  UINT地址,*一个;
  结构BUF *基点;  如果(BN< NDIRECT){
    如果((地址= IP-GT&; addrs的[BN])== 0)
      IP-> addrs的[BN] = ADDR = balloc(IP->开发);
    返回地址;
  }
  BN - = NDIRECT;  如果(BN< NINDIRECT){
    //加载间接块,如果有必要分配。
    如果((地址= IP-GT&; addrs的[NDIRECT])== 0)
      IP-> addrs的[NDIRECT] = ADDR = balloc(IP->开发);
    BP =面包(IP->开发,地址);
    A =(UINT *)BP-GT&;数据;
    如果((地址= A [BN])== 0){
      一个[BN] = ADDR = balloc(IP->开发);
      log_write(BP);
    }
    brelse(BP);
    返回地址;
  }  / *双间接* /
  BN - = NINDIRECT;
  如果(BN< NINDIRECT * NINDIRECT){
        //加载第二个间接块,如果有必要分配。
        如果((地址= IP-GT&; addrs的[NDIRECT + 1])== 0)// 2D块。 NDIRECT + 1得到的索引向量
          IP-> addrs的[NDIRECT + 1] = ADDR = balloc(IP->开发);        BP =面包(IP->开发,地址);
        A =(UINT *)BP-GT&;数据;
        如果((地址= A [BN /(NINDIRECT)])== 0){/ *获得第一个指数
                                                    间接。 (NINDIRECT为128)* /
              一个[BN /(NINDIRECT)] = ADDR = balloc(IP->开发);
              log_write(BP);
          }
          brelse(BP); / *释放双重间接表
                                       (主水平)* /        BP =面包(IP->开发,地址);
        A =(UINT *)BP-GT&;数据;         如果((地址= A [BN%(NINDIRECT))== 0){/ *获得第2级表* /
              一个[BN%(NINDIRECT)] = ADDR = balloc(IP->开发);
              log_write(BP);
          }        brelse(BP);
        返回地址;
    }   / *三重间接* /      BN - = NINDIRECT * NINDIRECT;
      如果(BN 4; * NINDIRECT * NINDIRECT){
        //加载第三间接块,如果有必要分配。
        如果((地址= IP-GT&; addrs的[NDIRECT + 2])== 0)// 3D块。 NDIRECT + 2来获得索引向量
          IP-> addrs的[NDIRECT + 2] = ADDR = balloc(IP->开发);        BP =面包(IP->开发,地址);
        A =(UINT *)BP-GT&;数据;        如果((地址= A [BN /(NINDIRECT * 4)])== 0){/ *获得2ST指数
                                                    间接。 (NINDIRECT为128)* /
              一个[BN /(NINDIRECT * 4)] = ADDR = balloc(IP->开发);
              log_write(BP);
          }
          brelse(BP);        BP =面包(IP->开发,地址);
        A =(UINT *)BP-GT&;数据;        如果((地址= A [BN /(NINDIRECT * NINDIRECT * 4))== 0){              一个[BN /(NINDIRECT * NINDIRECT * 4)] = ADDR = balloc(IP->开发);
              log_write(BP);
          }          brelse(BP);
         如果((地址= A [BN%(NINDIRECT * NINDIRECT * 4))== 0){
              一个[BN%(NINDIRECT * NINDIRECT * 4)] = ADDR = balloc(IP->开发);
              log_write(BP);
          }        brelse(BP);
        返回地址;
    }  恐慌(BMAP:超出范围);
}

mkfs.c:

 的#define统计xv6_stat //避免与主机结构统计冲突
#包括types.h中
#包括fs.h中
#包括stat.h
#包括param.hINT的nblocks = 20985;
INT n日志= LOGSIZE;
INT ninodes = 200;
INT大小= 21029;

bigfile.c:

 的#includetypes.h中
#包括stat.h
#包括user.h
#包括fcntl.h
空虚
帮帮我()
{
  的printf(1,用法:\\ NFILES<名称><字母GT;< NUM> \\ N
            例如NFILES foo的40 \\ N创建一个文件foo,与40倍的字母\\ n);
}空虚
num2str(INT I,焦炭海峡[3])
{
  海峡[2] =则i%10 +'0';
  I = I / 10;
  海峡[1] =则i%10 +'0';
  I = I / 10;
  海峡[0] =则i%10 +'0';
  I = I / 10;
}
#定义BUF_SZ 512INT
主(INT ARGC,CHAR *的argv [])
{
    INT I,计数,FD,N;
    //字符*名称;
    //字符℃;
    烧焦的buf [BUF_SZ]
    如果(argc个!= 4){
        帮帮我();
        出口();
    }
    数=的atoi(argv的[3]);
    如果((FD =打开(的argv [1],O_CREATE | O_RDWR))小于0){
        的printf(2,无法打开文件:%s \\ n,ARGV [1]);
        出口();
    }
    对于(i = 0; I< BUF_SZ;我++)
        的buf [I] = argv的[2] [0];
    对于(i = 0; I<计数/ BUF_SZ;我++)
        如果((N =写(FD,BUF,BUF_SZ))!= BUF_SZ)
        {
            的printf(2,失败1至写入次数=%d个\\ N,我* BUF_SZ);
            出口();
        }    对于(i = 0; I<计数%BUF_SZ;我++)
        如果((N =写入(FD,argv的[2],1))!= 1)
        {
            的printf(2,失败2写入次数=%d个\\ N,COUNT-I);
            出口();
        }  出口();
}


解决方案

1,该数量在 mkfs.c 定义的nblocks是不够的。

  INT的nblocks = 20985;
INT n日志= LOGSIZE;
INT ninodes = 200;
INT大小= 21029;

您已经定义:

 的#define MAXFILE(NDIRECT + NINDIRECT + NINDIRECT * NINDIRECT + 4 * NINDIRECT * NINDIRECT

等于:10 + 128 + 128 ^ 2 + 4 * 128 ^ 2 = 82058

只需选择一个号码的nblocks 的比82058更大,更新尺寸相应。

2.In您的BMAP()函数,在三联间接code,你的间接第一个层次是到了四入境阵列(如您在图中提到的)。
一旦你知道这些四项,你应该访问,你回到了双间接的问题,你已经解决了。

于是,为了知道哪些四个条目,你应该访问,您可以使用此:

  IF((地址= A [BN /(NINDIRECT * NINDIRECT))== 0){
  一个[BN /(NINDIRECT * NINDIRECT)] = ADDR = balloc(IP->开发);
  log_write(BP);
}

您再能降低亿像这样:

  BN  -  =((NINDIRECT * NINDIRECT)*(BN /(NINDIRECT * NINDIRECT)));

和再解决双间接的问题。

The original xv6-rev7 operating system contains:
12 directed blocks
1 indirect blcok(points to 128 blocks)

This means we have 140 blocks.
Each block's size is 512KB ==> 512 * 140 = 71,680 ~= 70KB is the limit of file's size in xv6.

I want to implemet triple indirect access in xv6 in order to support files with size of 40MB.

In order to do it I will need to implement double indirect before the triple indirect.
So I took 2 directed blocks from the 12 I had.
1 for the double indirect and the other for the triple indirect.
This is what I have right now:
Direct: 10 blocks
Single indirect: 128
Double indirect: 128*128
Triple indirect: 4*128*128 (I am using 4 instead of 128 because this is enough for 40MB)

This is why #define NDIRECT 10 and uint addrs[NDIRECT+3];

File's size limit = (10 + 128 + 128*128 + 4*128*128)*512kb = 42,013,696 ~= 42MB

So I understand the concept. The implementation of the triple-indirection is in function bmap in file fs.c.
This is how it looks:

For some reason when I am trying to create file with size of 8.5MB it fails:
I am using bochs emulator

I am also not sure to what values I need to change in mkfs.c:

int nblocks = 20985;
int nlog = LOGSIZE;
int ninodes = 200;
int size = 21029;

fs.h:

// On-disk file system format. 
// Both the kernel and user programs use this header file.

// Block 0 is unused.
// Block 1 is super block.
// Blocks 2 through sb.ninodes/IPB hold inodes.
// Then free bitmap blocks holding sb.size bits.
// Then sb.nblocks data blocks.
// Then sb.nlog log blocks.

#define ROOTINO 1  // root i-number
#define BSIZE 512  // block size

// File system super block
struct superblock {
  uint size;         // Size of file system image (blocks)
  uint nblocks;      // Number of data blocks
  uint ninodes;      // Number of inodes.
  uint nlog;         // Number of log blocks
};

#define NDIRECT 10
#define NINDIRECT (BSIZE / sizeof(uint))
#define MAXFILE (NDIRECT + NINDIRECT + NINDIRECT*NINDIRECT + 4*NINDIRECT*NINDIRECT)

// On-disk inode structure
struct dinode {
  short type;           // File type
  short major;          // Major device number (T_DEV only)
  short minor;          // Minor device number (T_DEV only)
  short nlink;          // Number of links to inode in file system
  uint size;            // Size of file (bytes)
  uint addrs[NDIRECT+3];   // Data block addresses
};

// Inodes per block.
#define IPB           (BSIZE / sizeof(struct dinode))

// Block containing inode i
#define IBLOCK(i)     ((i) / IPB + 2)

// Bitmap bits per block
#define BPB           (BSIZE*8)

// Block containing bit for block b
#define BBLOCK(b, ninodes) (b/BPB + (ninodes)/IPB + 3)

// Directory is a file containing a sequence of dirent structures.
#define DIRSIZ 14

struct dirent {
  ushort inum;
  char name[DIRSIZ];
};

fs.c:

// Return the disk block address of the nth block in inode ip.
// If there is no such block, bmap allocates one.
static uint
bmap(struct inode *ip, uint bn)
{
  uint addr, *a;
  struct buf *bp;

  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);
    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;
  }

  /* Double indirect */
  bn -= NINDIRECT;
  if(bn < NINDIRECT*NINDIRECT){
        // Load 2nd indirect block, allocating if necessary.
        if((addr = ip->addrs[NDIRECT+1]) == 0) // 2d block. NDIRECT+1 is to get the index vector
          ip->addrs[NDIRECT+1] = addr = balloc(ip->dev);

        bp = bread(ip->dev, addr);
        a = (uint*)bp->data;
        if ((addr = a[bn/(NINDIRECT)]) == 0) { /* get index for 1st
                                                    indirection. (NINDIRECT is 128) */
              a[bn/(NINDIRECT)] = addr = balloc(ip->dev);
              log_write(bp);
          }
          brelse(bp);               /* release the double indirect table
                                       (main level) */

        bp = bread(ip->dev, addr);
        a = (uint*)bp->data;

         if ((addr = a[bn%(NINDIRECT)]) == 0) { /*  get the 2nd level table */
              a[bn%(NINDIRECT)] = addr = balloc(ip->dev);
              log_write(bp);
          }

        brelse(bp);
        return addr;
    }

   /* Triple indirect */

      bn -= NINDIRECT*NINDIRECT;
      if(bn < 4*NINDIRECT*NINDIRECT){
        // Load 3rd indirect block, allocating if necessary.
        if((addr = ip->addrs[NDIRECT+2]) == 0) // 3d block. NDIRECT+2 is to get the index vector
          ip->addrs[NDIRECT+2] = addr = balloc(ip->dev);

        bp = bread(ip->dev, addr);
        a = (uint*)bp->data;

        if ((addr = a[bn/(NINDIRECT*4)]) == 0) { /* get index for 2st
                                                    indirection. (NINDIRECT is 128) */
              a[bn/(NINDIRECT*4)] = addr = balloc(ip->dev);
              log_write(bp);
          }
          brelse(bp);

        bp = bread(ip->dev, addr);
        a = (uint*)bp->data;

        if ((addr = a[bn/(NINDIRECT*NINDIRECT*4)]) == 0) { 

              a[bn/(NINDIRECT*NINDIRECT*4)] = addr = balloc(ip->dev);
              log_write(bp);
          }

          brelse(bp);               


         if ((addr = a[bn%(NINDIRECT*NINDIRECT*4)]) == 0) { 
              a[bn%(NINDIRECT*NINDIRECT*4)] = addr = balloc(ip->dev);
              log_write(bp);
          }

        brelse(bp);
        return addr;
    }

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

mkfs.c:

#define stat xv6_stat  // avoid clash with host struct stat
#include "types.h"
#include "fs.h"
#include "stat.h"
#include "param.h"

int nblocks = 20985;
int nlog = LOGSIZE;
int ninodes = 200;
int size = 21029;

bigfile.c:

#include "types.h"
#include "stat.h"
#include "user.h"
#include "fcntl.h"
void
help()
{
  printf(1, "usage:\nfiles <name> <letter> <num>\n"
            "e.g. nfiles foo a 40\n creates a file foo, with 40 times the letter a\n");
}

void
num2str(int i, char str[3])
{
  str[2]=i%10+'0';
  i=i/10;
  str[1]=i%10+'0';
  i=i/10;
  str[0]=i%10+'0';
  i=i/10;
}
#define BUF_SZ 512

int
main(int argc, char *argv[])
{
    int i, count, fd, n;
    // char *name;
    // char c;
    char buf[BUF_SZ];
    if (argc !=4) {
        help();
        exit();
    }
    count = atoi(argv[3]);
    if((fd=open(argv[1], O_CREATE|O_RDWR))<0) {
        printf(2,"Failed to open file: %s\n", argv[1]);
        exit();
    }
    for (i=0; i<BUF_SZ;i++)
        buf[i]=argv[2][0];
    for (i=0; i<count/BUF_SZ;i++)
        if ((n=write(fd,buf,BUF_SZ)) != BUF_SZ)
        {
            printf(2,"Failed 1 to Write count=%d\n",i*BUF_SZ);
            exit();
        }

    for (i=0; i<count%BUF_SZ;i++)
        if ((n=write(fd,argv[2],1)) != 1)
        {
            printf(2,"Failed 2 to Write count=%d\n",count-i);
            exit();
        }

  exit();
}

解决方案

1.The number of nblocks which is defined in mkfs.c is insufficient.

int nblocks = 20985;
int nlog = LOGSIZE;
int ninodes = 200;
int size = 21029;

You have defined:

#define MAXFILE (NDIRECT + NINDIRECT + NINDIRECT*NINDIRECT + 4*NINDIRECT*NINDIRECT

which equals: 10+128+128^2+4*128^2 = 82058.

Just pick a number of nblocks which is greater than 82058, and update size accordingly.

2.In your bmap() function, in the triple indirection code, your first level of indirection is to a four-entry array (as you mentioned in your diagram). Once you know to which of these four entries you should access, you're back with the double indirection problem, which you already solved.

So, in order to know which of the four entries you should access, you can use this:

if((addr = a[bn/(NINDIRECT*NINDIRECT)]) == 0){
  a[bn/(NINDIRECT*NINDIRECT)] = addr = balloc(ip->dev);
  log_write(bp);
}

You then could decrease bn like so:

bn -= ((NINDIRECT*NINDIRECT)*(bn/(NINDIRECT*NINDIRECT)));

and solve the double indirection problem again.

这篇关于XV6努力实现XV6操作系统三级间接时候崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆