iT邦幫忙

0

[6.1810][code] xv6 的 FileSystem (六) : Directory Layer

  • 分享至 

  • xImage
  •  

系列文章 : [6.1810] 跟著 MIT 6.1810 學習基礎作業系統觀念

大綱

  • kernel/fs.h/dirent
  • kernel/fs.c/namecmp
  • kernel/fs.c/dirlookup
  • kernel/fs.c/dirlink

kernel/fs.h/dirent

#define DIRSIZ 14

struct dirent {
  ushort inum;
  char name[DIRSIZ];
};
  • direct
    • inum 佔 2 bytes
    • char name[D] 佔 14 bytes ( DIRSIZ = 14),代表檔案名稱最長為 14 個字元
    • 所以整個 struct dirent 佔 16 bytes
  • inum
    • 這個 directory entry 所指向的 inode number。
    • 假如 inum == 0,代表這個 directory entry 是空的 ( empty ),可以被其他人所使用。
    • 假如 inum != 0,這代表了這是一個在 disk-hardware 裡面的 inode 的 number,該 inode 儲存了這個 directory entry 所指向的檔案的 metadata。
  • name
    • 檔案名稱。假如檔案名稱剛好是 14 個字元的話,就不會有 null-terminator ( \0 )。


kernel/fs.c/namecmp

int
namecmp(const char *s, const char *t)
{
  return strncmp(s, t, DIRSIZ);
}

比對檔案名稱,因為檔案名稱最長為 DIRSIZ,所以這邊 strncmp 的長度設為 DIRSIZ



kernel/fs.c/dirlookup

// Look for a directory entry in a directory.
// If found, set *poff to byte offset of entry.
struct inode*
dirlookup(struct inode *dp, char *name, uint *poff)
{
  • 嘗試在一個 directory inode 裡面,找尋目標檔案。
  • struct inode *dp
    • 指向一個 directory inode 的 in-memory-struct-inode。
  • char *name
    • 目標的檔案名稱,會在 dp 的 directory entry 嘗試去尋找符合這個名稱的檔案
  • uint *poff
    • 假如能夠找到該檔案,則 poff 會記錄該檔案在 directory inode 裡面的 directory entry 的偏移量
  • return value
    • 成功 : 回傳一個 in-memory-struct-inode
    • 失敗 : 例如找不到該檔案,回傳 0 ( null pointer )

  uint off, inum;
  struct dirent de;

  if(dp->type != T_DIR)
    panic("dirlookup not DIR");

會去看該 inode 的類型是不是 directory
假如不是的話,就該馬上發出 panic。


  for(off = 0; off < dp->size; off += sizeof(de)){
    if(readi(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de))
      panic("dirlookup read");
    if(de.inum == 0)
      continue;
    if(namecmp(name, de.name) == 0){
      // entry matches path element
      if(poff)
        *poff = off;
      inum = de.inum;
      return iget(dp->dev, inum);
    }
  }

  return 0;
}
  • 這邊會去完整遍尋一遍 directory entries
  • 用 readi 取得該 in-memory-struct-inode 的檔案內容,因為該 inode 的 type 是 T_DIR,所以檔案內容預期會是 directory entries
  • 用 namecmp 去比對檔案名稱
  • 假如能夠找到該檔案,就用 poff 去記錄找到該檔案時的偏移量。
  • 用 iget 去取得該檔案的 in-memory-struct-inode


kernel/fs.c/dirlink

// Write a new directory entry (name, inum) into the directory dp.
// Returns 0 on success, -1 on failure (e.g. out of disk blocks).
int
dirlink(struct inode *dp, char *name, uint inum)
{
  • 會將 inode number 為 inum 的 struct-inode,以 name 為檔案名稱,放進 dp 這個 directory 裡面。
  • struct inode *dp : 表示該 directory 的 in-memory-struct-inode
  • char *name : 新增檔案的檔案名稱。
  • uint inum : 新增檔案的 inode number。
  • return value
    • 0 : 成功在這個 directory 建立一個新的 directory entry。
    • -1 : 失敗。可能是因為這個 directory 已經有相同名稱的檔案了,也有可能是因為 disk 已經滿了。
  • 因為這個是在這個 directory 新增 inode number 為 inum 的檔案,所以 inum 這個檔案其實可以重複加進不同的 directory 裡面。或甚至是,以不同的檔案名稱儲存在相同的 directory 裡面。

  int off;
  struct dirent de;
  struct inode *ip;

  // Check that name is not present.
  if((ip = dirlookup(dp, name, 0)) != 0){
    iput(ip);
    return -1;
  }
  • 因為 dirlookup 裡面會去呼叫 iget,所以在這邊沒有要繼續使用該 inode 的話,需要自行 iput
  • 假如這個檔案名稱已經存在了的話,就 return -1 表示失敗
    • 也就是說,假如換一個檔案名稱,同樣的 inode 可以出現在同一個 directory 裡面好幾次。

  // Look for an empty dirent.
  for(off = 0; off < dp->size; off += sizeof(de)){
    if(readi(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de))
      panic("dirlink read");
    if(de.inum == 0)
      break;
  }

遍尋這個 directory 的所有 directory entry,找到有空位的地方,就把 off 記起來,並 break 退出迴圈。


  strncpy(de.name, name, DIRSIZ);
  de.inum = inum;
  if(writei(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de))
    return -1;

  return 0;
}

把目標 inum 放在目標 directory entry 裡面。




圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言