2015-06-15 41 views
0

原始XV6-rev7操作系统包含:
12引导块
1个间接块,旋转(点到128个块)XV6崩溃试图实现在XV6操作系统三重间接当

这意味着我们具有140块。
每块的大小是512KB ==> 512 * 140 = 71,680〜= 70KB是xv6中文件大小的限制。

我想在xv6中实现三重间接访问,以支持大小为40MB的文件。

为了做到这一点,我需要在三重间接之前实现双重间接。
所以我从12我拿了2个导向块。
1为双重间接,另一为三重间接。
这就是我现在所拥有的:
直接:10块
单间接:128
双间接:128 * 128
三重间接:4 * 128 * 128(我用4,而不是128,因为这是足够的40MB)

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

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

所以我理解这个概念。 三重间接的实现在函数bmap中的文件fs.c中。
这是它的外观:
enter image description here

因为当我试图创建一个8.5MB的文件大小失败某些原因: enter image description here
我使用的Bochs模拟器

我也不知道我需要在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(); 
} 

回答

2

1.在mkfs.c中定义的nblock数量不足。

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

您已定义:

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

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

只需选择一个号码的nblocks这是更大的比82058更高,并相应地更新size

2.在您的bmap()函数中,在三重间接代码中,您的第一级间接指向四个条目的数组(如您在图中所述)。 一旦你知道了你应该访问的这四个条目中的哪一个,你就回到了你已经解决的双重间接问题。

所以,要想知道其中四个项目,你应该访问,您可以使用此:

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

然后,您可以降低bn像这样:

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

,解决了双间接问题再次。