Linux mount代码分析

1.    数据结构

vfsmount

struct vfsmount {
                struct list_head mnt_hash;          // hash表
                struct vfsmount*mnt_parent;   /* fs we are mounted on */
                struct dentry*mnt_mountpoint;              /* dentry ofmountpoint */
                struct dentry *mnt_root;              /* root of the mounted tree */|
                struct super_block*mnt_sb;      /* pointer to superblock */
                struct list_headmnt_mounts;    /* list of children,anchored here */
                struct list_headmnt_child;         /* and going throughtheir mnt_child */
                int mnt_flags;
                /* 4 bytes hole on 64bitsarches */
                const char *mnt_devname;         /* Name of device e.g. /dev/dsk/hda1 */
                struct list_head mnt_list;
                struct list_headmnt_expire;      /* link in fs-specificexpiry list */
                struct list_headmnt_share;        /* circular list ofshared mounts */
                struct list_headmnt_slave_list;/* list of slave mounts */
                struct list_headmnt_slave;         /* slave list entry */
                struct vfsmount*mnt_master;  /* slave is onmaster->mnt_slave_list */
                struct mnt_namespace*mnt_ns;             /* containingnamespace */
                int mnt_id;                                         /*mount identifier */
                int mnt_group_id;                           /* peer groupidentifier */
                /*
                 * We put mnt_count & mnt_expiry_mark atthe end of struct vfsmount
                 * to let these frequently modified fields in aseparate cache line
                 * (so that reads of mnt_flags wont ping-pongon SMP machines)
                 */
                atomic_t mnt_count;
                int mnt_expiry_mark;                    /* true if marked for expiry*/
                int mnt_pinned;
                int mnt_ghosts;
                int mnt_writers;
};

namespace

struct mnt_namespace {
                atomic_t                              count;
                struct vfsmount *            root;
                struct list_head                list;
                wait_queue_head_t poll;
                int event;
};

2.    初始化

void __init mnt_init(void)
                init_rwsem(&namespace_sem);
                static struct kmem_cache *mnt_cache =
                                kmem_cache_create("mnt_cache",sizeof(struct vfsmount),
                                                0, SLAB_HWCACHE_ALIGN |SLAB_PANIC, NULL);
                static struct list_head * mount_hashtable= (struct list_head *)__get_free_page(GFP_ATOMIC);
                for (u = 0; u <HASH_SIZE; u++)
                                INIT_LIST_HEAD(&mount_hashtable[u]);
                // 下面这行是初始化sysfs,放在这里其实不太好,但由于初始化sysfs时用到了mount操作,而下面做其它文件系统mount时又用到sysfs,所以也只能放这里。
                sysfs_init();       
                fs_kobj =kobject_create_and_add("fs", NULL); //在sysfs中加上fs节点
                init_rootfs();
                init_mount_tree();

mnt_init最后调用了init_rootfs和init_mount_tree两个函数,下面分别来看一下。

2.1 init_rootfs

int __init init_rootfs(void)
                int err;
                err =bdi_init(&ramfs_backing_dev_info);
                // 注册rootfs文件系统
                        err =register_filesystem(&rootfs_fs_type);

rootfs_fs_type定义在fs/ramfs/inode.c。

static struct file_system_type rootfs_fs_type = {
                .name                   = "rootfs",
                .get_sb                 = rootfs_get_sb,
                .kill_sb                 =kill_litter_super,
};

2.2 init_mount_tree

static void __init init_mount_tree(void)

                // 得到rootfs的vfsmount结构,设置里面的超级块等信息,见下文

                structvfsmount *mnt =do_kern_mount("rootfs",0, "rootfs", NULL);

                // 根据mnt新建一个mnt_namespace,见下文

                structmnt_namespace *ns =create_mnt_ns(mnt);

                init_task.nsproxy->mnt_ns= ns;

                get_mnt_ns(ns);

                root.mnt= ns->root;

                root.dentry= ns->root->mnt_root;

                // 由于调init_mount_tree时init进程还没启动,下面的current宏由最开始时设置的栈指针决定,应该就是init_task的taskstruct结构体。

                set_fs_pwd(current->fs,&root);

                set_fs_root(current->fs,&root);

 

do_kern_mount的作用是分配一个vfsmount,同时里面初始化了super block。

struct vfsmount * do_kern_mount(const char *fstype, intflags, const char *name, void *data)

                structfile_system_type *type = get_fs_type(fstype);

                structvfsmount *mnt;

                mnt =vfs_kern_mount(type, flags, name, data);

                put_filesystem(type);

                returnmnt;

struct vfsmount * vfs_kern_mount(struct file_system_type*type, int flags, const char *name, void *data)

                structvfsmount * mnt = alloc_vfsmnt(name);

                type->get_sb(type,flags, name, data, mnt);

                //mnt_mountpoint设置为mnt_root,即挂载点为自己

                mnt->mnt_mountpoint= mnt->mnt_root;

                // mnt_parent设成自己

                mnt->mnt_parent= mnt;

struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)

                structmnt_namespace *new_ns = alloc_mnt_ns();

                mnt->mnt_ns= new_ns;

                new_ns->root= mnt;

                list_add(&new_ns->list,&new_ns->root->mnt_list);

3.    文件系统加载

mount操作包括remount,move_mount, mount块设备,mountloop设备等,都由内核函数do_mount完成。本质上,mount操作的过程就是新建一个vfsmount结构,然后将此结构和挂载点关联。关联之后,目录查找时就能沿着vfsmount挂载点一级级向下查找文件了。

关于如何经过vfsmount查找文件,可以看函数kern_path。kern_path的作用为根据路径得到dentry和inode结构,里面会调用到path_walk,最终调用__follow_mount

 

下面看一下mount块设备的实现。
long do_mount(char *dev_name, char *dir_name, char *type_page,
                                unsignedlong flags, void *data_page)

                struct path path;

                // 得到挂载点的vfsmount和dentry结构,保存在structpath中。

                kern_path(dir_name,LOOKUP_FOLLOW, &path);

                。。。

                // 对块设备,调用到do_new_mount

                do_new_mount(&path, type_page, flags,mnt_flags, dev_name, data_page);

 

static int do_new_mount(struct path *path, char *type, int flags, int mnt_flags, char*name, void *data)

                struct vfsmount * mnt =do_kern_mount(type, flags, name, data);

                do_add_mount(mnt, path,mnt_flags, NULL);

 

int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags, structlist_head *fslist)

    // 找到该目录的当前挂载点的vfsmount和dentry结构

    while (d_mountpoint(path->dentry)&& follow_down(path))             ;

                // graft_tree主要作用是将新的vfsmount加到mounttree。

                graft_tree (newmnt, path);

 

loopmount与mount块设备类似,根据被加载设备的superblock、dentry结构新建一个vfsmount结构,将该vfsmount挂到mounttree上。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值