6.S081 Lab9: file system

本文详细解读了fs.h和file.h中dinode和inode结构的修改,涉及宏定义、bmap和itrunc函数扩展,以及sys_link和sys_symlink系统调用实现。讨论了如何优化大型文件存储和处理,以及在处理符号链接时的关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Large files

  1. 修改fs.hstruct dinode字段并且修改、增加宏:

    #define NDIRECT 11
    #define NINDIRECT (BSIZE / sizeof(uint))
    #define NDINDIRECT (NINDIRECT * NINDIRECT)
    #define MAXFILE (NDIRECT + NINDIRECT + NDINDIRECT)
    
    struct dinode {
        short type;           // File type
        short major;          // Major device number (T_DEVICE only)
        short minor;          // Minor device number (T_DEVICE only)
        short nlink;          // Number of links to inode in file system
        uint size;            // Size of file (bytes)
        uint addrs[NDIRECT+2];   // Data block addresses
    };
    
  2. 修改file.hstruct 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];
    };
    
  3. fs.c的函数bmap中增加字段:

    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;
      }
      bn -= NINDIRECT;
    
      if(bn < NDINDIRECT) {
        if(!(addr = ip->addrs[NDIRECT+1]))
          ip->addrs[NDIRECT+1] = addr = balloc(ip->dev);
        
        bp = bread(ip->dev, addr);
        a = (uint*)bp->data;
        if(!(addr = a[bn/NINDIRECT])) {
          a[bn/NINDIRECT] = addr = balloc(ip->dev);
          log_write(bp);
        }
        brelse(bp);
    
        bp = bread(ip->dev, addr);
        a = (uint*)bp->data;
        if(!(addr = a[bn%NINDIRECT])) {
          a[bn%NINDIRECT] = addr = balloc(ip->dev);
          log_write(bp);
        }
        brelse(bp);
    
        return addr;
      }
    
      panic("bmap: out of range");
    }
    
  4. fs.c的函数itrunc中增加字段:

        void
    itrunc(struct inode *ip)
    {
      int i, j;
      struct buf *bp, *bp2;
      uint *a, *a2;
    
      for(i = 0; i < NDIRECT; i++){
        if(ip->addrs[i]){
          bfree(ip->dev, ip->addrs[i]);
          ip->addrs[i] = 0;
        }
      }
    
      if(ip->addrs[NDIRECT]){
        bp = bread(ip->dev, ip->addrs[NDIRECT]);
        a = (uint*)bp->data;
        for(j = 0; j < NINDIRECT; j++){
          if(a[j])
            bfree(ip->dev, a[j]);
        }
        brelse(bp);
        bfree(ip->dev, ip->addrs[NDIRECT]);
        ip->addrs[NDIRECT] = 0;
      }
    
      // double indirect inode is exist?
      if(ip->addrs[NDIRECT+1]) {
        bp = bread(ip->dev, ip->addrs[NDIRECT+1]);
        a = (uint*)bp->data;
    
        for(i = 0; i < NINDIRECT; ++i) {
          // indirect inode is exist?
          if(a[i]) {
            bp2 = bread(ip->dev, a[i]);
            a2 = (uint*)bp2->data;
    
            for(j = 0; j < NINDIRECT; ++j)
              // block is exist?
              if(a2[j])
                bfree(ip->dev, a2[j]);
            brelse(bp2);
            bfree(ip->dev, a[i]);
          }
        }
    
        brelse(bp);
        bfree(ip->dev, ip->addrs[NDIRECT+1]);
        ip->addrs[NDIRECT+1] = 0;
      }
    
      ip->size = 0;
      iupdate(ip);
    }
    

Symbolic Links

  1. 注册sys_link系统调用:

    # usys.pl
    entry("symlink");
    
    // user.h
    int symlink(char* target, char* path);
    
    // syscall.h
    #define SYS_symlink 22
    
    // syscall.c
    extern uint64 sys_symlink(void);
    
    [SYS_symlink] sys_symlink,
    
    # Makefile
    $U/_symlinktest\
    
  2. 增加宏,增加struct inode字段:

    // fcntl.h
    #define O_NOFOLLOW 0x004
    // stat.h
    #define T_SYMLINK 4
    
  3. 定义函数sys_symlink

    uint64 sys_symlink(void) {
        char target[MAXPATH];
        char path[MAXPATH];
        struct inode *ip;
    
        if(argstr(0, target, MAXPATH) < 0 || argstr(1, path, MAXPATH) < 0)
            return -1;
    
        begin_op();
    
        if((ip = create(path, T_SYMLINK, 0, 0)) == 0) {
            end_op();
            return -1;
        }
    
        if(writei(ip, 0, (uint64)target, 0, MAXPATH) != MAXPATH)
            panic("sys_symlink: writei");
        
        iunlockput(ip);
        end_op();
    
        return 0;
    }
    
  4. 修改函数sys_open

    uint64
    sys_open(void)
    {
        char path[MAXPATH];
        int fd, omode;
        struct file *f;
        struct inode *ip;
        int n;
        int depth = 0;
    
        if((n = argstr(0, path, MAXPATH)) < 0 || argint(1, &omode) < 0)
            return -1;
    
        begin_op();
    
        if(omode & O_CREATE){
            ip = create(path, T_FILE, 0, 0);
            if(ip == 0){
                end_op();
                return -1;
            }
        } else {
            if((ip = namei(path)) == 0){
                end_op();
                return -1;
            }
            ilock(ip);
    
            while(ip->type==T_SYMLINK && !(omode&O_NOFOLLOW) && depth<MAXFOLLOWDEPTH) {
                readi(ip, 0, (uint64)path, 0, MAXPATH);
                iunlockput(ip);
                if((ip = namei(path)) == 0) {
                    end_op();
                    return -1;
                }
                ilock(ip);
                ++depth;
            }
    
            if(depth == MAXFOLLOWDEPTH) {
                iunlock(ip);
                end_op();
                return -1;
            }
    
            if(ip->type == T_DIR && omode != O_RDONLY){
                iunlockput(ip);
                end_op();
                return -1;
            }
        }
    
        if(ip->type == T_DEVICE && (ip->major < 0 || ip->major >= NDEV)){
            iunlockput(ip);
            end_op();
            return -1;
        }
    
        if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){
            if(f)
                fileclose(f);
            iunlockput(ip);
            end_op();
            return -1;
        }
    
        if(ip->type == T_DEVICE){
            f->type = FD_DEVICE;
            f->major = ip->major;
        } else {
            f->type = FD_INODE;
            f->off = 0;
        }
        f->ip = ip;
        f->readable = !(omode & O_WRONLY);
        f->writable = (omode & O_WRONLY) || (omode & O_RDWR);
    
        if((omode & O_TRUNC) && ip->type == T_FILE){
            itrunc(ip);
        }
    
        iunlock(ip);
        end_op();
    
        return fd;
    }
    

总结

在这里插入图片描述

fs的源码看了几天给我看麻了,网上的思路也不尽相同,任务2基本是毛来的,歇一歇再继续。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值