iT邦幫忙

0

[6.1810][code] xv6 的 FileSystem (七) : Pathname layer

  • 分享至 

  • xImage
  •  

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

大綱

  • kernel/fs.c/skipelem
  • kernel/fs.c/namex
  • kernel/fs.c/namei
  • kernel/fs.c/nameiparent

kernel/fs.c/skipelem

// Copy the next path element from path into name.
// Return a pointer to the element following the copied one.
// The returned path has no leading slashes,
// so the caller can check *path=='\0' to see if the name is the last one.
// If no name to remove, return 0.
//
// Examples:
//   skipelem("a/bb/c", name) = "bb/c", setting name = "a"
//   skipelem("///a//bb", name) = "bb", setting name = "a"
//   skipelem("a", name) = "", setting name = "a"
//   skipelem("", name) = skipelem("////", name) = 0
//
static char*
skipelem(char *path, char *name)
{
  • 這個 function 是在路徑解析的過程中,很好用的一個 helper function。
    • 例如現在有一個路徑 a/bb/c,這個 function 會抽出第一個 a,並回傳指標指向字串 bb/c
  • path : 輸入的字串,例如 a/bb/c
  • name : 路徑上的第一個名稱,例如 b
  • return value : 剩餘的字串,例如 bb/c
  • 要注意
    • name 是複製過去的
    • return value 並不會 allocate 一塊新的記憶體,而是原本 path 指標加上偏移量。
    • 當呼叫 skipelem(“c”, name) 的時候,name 會回傳 “c”,return value 會是指向 null-terminator 的指標 ( “\0” ),而不是 0!!
    • 呼叫 skipelem(“\0”, name) 的回傳值才會是 0。

kernel/fs.c/namex

// Look up and return the inode for a path name.
// If parent != 0, return the inode for the parent and copy the final
// path element into name, which must have room for DIRSIZ bytes.
// Must be called inside a transaction since it calls iput().
static struct inode*
namex(char *path, int nameiparent, char *name)
{
  • 例如現在有一個 path 是 /a/b/c
    • 當 nameiparent == 0 的時候,我們該回傳的是 c 的 struct-inode
    • 當 nameiparent == 1 的時候,我們該回傳的是 b 這個的 struct-inode ( b 本身是 directory ),並且 name 設為 “c”
  • 因為這個 function 會呼叫 iput,因此可能對 disk-hardware 進行寫入,所以需要在一個 transaction 的範圍內 ( 也就是夾在 begin_op 跟 end_op 之中。 )
  • char *path
    • 希望解析的路徑
  • int nameiparent
    • 實際上是一個 boolean flag,上面有對這個 boolean 的解釋。
  • char *name
    • 以上面的範例為例,假如 nameiparent == 1,會回傳 “c”
  • return value
    • val == 0 : 沒有成功解析該路徑
    • val != 0 : 目標 struct-inode 的指標

  struct inode *ip, *next;

  if(*path == '/')
    ip = iget(ROOTDEV, ROOTINO);
  else
    ip = idup(myproc()->cwd);
  • 假如路徑是由 / 開頭,則從根節點開始走訪 path。
  • 假如路徑不是由 / 開頭,則由當前的路徑開始走訪 path。

  while((path = skipelem(path, name)) != 0){
    ilock(ip);
    if(ip->type != T_DIR){
      iunlockput(ip);
      return 0;
    }
    if(nameiparent && *path == '\0'){
      // Stop one level early.
      iunlock(ip);
      return ip;
    }
    if((next = dirlookup(ip, name, 0)) == 0){
      iunlockput(ip);
      return 0;
    }
    iunlockput(ip);
    ip = next;
  }
  • ilock
    • 拿取 ip 的 sleep-lock
    • 可能會從 disk-hardware 讀取 struct-dinode 到 struct-inode
  • nameiparent
    • 假如是 true 的話,會提早退出 while-loop,因為要拿的是目標檔案名稱 ( e.g. “a/b/c” ) 的 parent 的 inode ( e.g. “a/b” 中的 b )
  • dirlookup
    • 給予一個 type 為 T_DIR 的 struct-inode,找尋底下的 directory entry 是否有名稱為 name 的檔案 ( struct-inode ),有的話便回傳該 struct-inode

  if(nameiparent){
    iput(ip);
    return 0;
  }

假如 nameiparent == 1,則應該要在 while 迴圈裡面就 return 了,走到這邊明顯不合理。
因路徑走訪失敗, return 0。


  return ip;
}

回傳目標 struct-inode 的指標。


kernel/fs.c/namei

struct inode*
namei(char *path)
{
  char name[DIRSIZ];
  return namex(path, 0, name);
}

會呼叫 namex,參數 nameiparent 會設為 0,所以不會在意 name 被設為什麼值。


kernel/fs.c/nameiparent

struct inode*
nameiparent(char *path, char *name)
{
  return namex(path, 1, name);
}

會呼叫 namex,參數 nameiparent 會設為 1,所以在意 name 被設為什麼值。



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

尚未有邦友留言

立即登入留言