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目录,然后为以后挂载文件系统提供挂载点 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值