rootfs文件系統的註冊和掛載

rootfs文件系統是由init_rootfs()完成的。

int __init init_rootfs(void)
{
  int err;
 
  err = bdi_init(&ramfs_backing_dev_info);
  if (err)
    return err;
  err = register_filesystem(&rootfs_fs_type);
  if (err)
    bdi_destroy(&ramfs_backing_dev_info);
 
  return err;
}
int register_filesystem(struct file_system_type * fs)
{
  int res = 0;
  struct file_system_type ** p;
 
  BUG_ON(strchr(fs->name, '.'));
  if (fs->next)
    return -EBUSY;
  INIT_LIST_HEAD(&fs->fs_supers);
  write_lock(&file_systems_lock);
  p = find_filesystem(fs->name, strlen(fs->name));
  if (*p)
    res = -EBUSY;
  else
    *p = fs;
  if(strncmp(fs->name, "rootfs", strlen(fs->name)) == 0)
    printk(KERN_WARNING 0x%x,0x%x,0x%x,",file_systems,file_systems->next,file_systems->next->next);
  write_unlock(&file_systems_lock);
  return res;
}

註冊過程可以參考上篇文章sysfs文件系統的註冊過程。

我在該函數中加入打印語句,打印全局變量file_systemsfile_systems->next,

file_systems->next->next,在其他地方也加有打印語句,打印全局變量rootfs_fs_type

Sysfs_fs_type的地址。打印結果如下:

&sysfs_fs_type = 0x802c7550

&rootfs_fs_type = 0x802c7810

file_systems = 0x802c7550

file_systems->next = 0x802c7810

file_systems->next->next = 0x0

可見file_systems指向&sysfs_fs_typefile_systems->next 也就是&sysfs_fs_type->next指向

&rootfs_fs_type,而 file_systems->next->next 也就是&rootfs_fs_type->next爲空。因爲此時只註冊了兩個文件系統。打印結果也驗證了上篇文章的圖一。

 下面來看看rootfs文件系統的掛載和根目錄的建立

static void __init init_mount_tree(void)
{
  struct vfsmount *mnt;
  struct mnt_namespace *ns;
  struct path root;
 
  mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
  if (IS_ERR(mnt))
    panic("Can't create rootfs");
  ns = create_mnt_ns(mnt);
  if (IS_ERR(ns))
    panic("Can't allocate initial namespace");
 
  init_task.nsproxy->mnt_ns = ns;
  /*ns->count = 2*/
  get_mnt_ns(ns);
 
  /*將根目錄的掛載點和目錄項設置爲
   *掛載rootfs時生成的掛載點和目錄項
   */
  root.mnt = ns->root;
  root.dentry = ns->root->mnt_root;
 
  set_fs_pwd(current->fs, &root);
  set_fs_root(current->fs, &root);
}

1.

rootfs文件系統的掛載是由do_kern_mount("rootfs", 0, "rootfs", NULL)完成。

 掛載過程參考sysfs文件系統的掛載過程,這裏只畫出掛載後的主要結構之間關係圖。

2.

掛載完成後,會創建一個namespace,並將rootfs添加進去

struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)
{
  struct mnt_namespace *new_ns;
 
  new_ns = alloc_mnt_ns();
  if (!IS_ERR(new_ns)) {
    /*建立namespace和root mnt之間的關係*/
    mnt->mnt_ns = new_ns;
    new_ns->root = mnt;
    /*???*/
    list_add(&new_ns->list, &new_ns->root->mnt_list);
  }
  return new_ns;
}
static struct mnt_namespace *alloc_mnt_ns(void)
{
  struct mnt_namespace *new_ns;
  /*分配一個namespace*/
  new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
  if (!new_ns)
    return ERR_PTR(-ENOMEM);
  /*ns->count = 1*/
  atomic_set(&new_ns->count, 1);
  new_ns->root = NULL;
  INIT_LIST_HEAD(&new_ns->list);
  init_waitqueue_head(&new_ns->poll);
  new_ns->event = 0;
  return new_ns;
}

3.代碼的最後兩行設置init進程的根目錄和當前目錄,這樣所有以後從 init進程 fork 來的進程也都先天地繼承了這一信息

以上講了一大堆數據結構的來歷,其實最終目的不過是要在內存中建立一顆 VFS 目錄樹而已,更確切地說, init_mount_tree() 這個函數爲 VFS 建立了根目錄 "/",而一旦有了根,那麼這棵數就可以發展壯大,比如可以通過系統調用 sys_mkdir 在這棵樹上建立新的葉子節點等。例如建立一個dev目錄,然後爲以後掛載文件系統提供掛載點 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章