Linux内核---43.文件系统的挂载
2016-07-09 10:22
531 查看
一. 临时文件系统的挂载过程
系统开始时先挂载了一个临时的文件系统,通过这个临时的文件系统
init/main.c
start_kernel
{
vfs_caches_init(totalram_pages); ;在fs/dcache.c:创建一个虚拟的文件系统
--> mnt_init ;在fs/namespace.c中
--> init_rootfs ;1.在fs/ramfs/inode.c中
--> init_mount_tree(); ;2.在fs/namespace.c中
}
1.在fs/ramfs/inode.c中
int __init init_rootfs(void)
{
bdi_init(&ramfs_backing_dev_info); //初始化ramfs_backing_dev_info结构体
register_filesystem(&rootfs_fs_type); //1.1注册rootfs_fs_type,
} 即把rootfs_fs_type添加到全局变量中
static struct backing_dev_info ramfs_backing_dev_info = {
.name = "ramfs",
.ra_pages = 0, /* No
readahead */
.capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK |
BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |
BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,
};
static struct file_system_type rootfs_fs_type = {
.name = "rootfs",
.mount = rootfs_mount,
.kill_sb = kill_litter_super,
};
1.1全局变量file_systems链表中将参数fs添加进来
int register_filesystem(struct file_system_type * fs)
{
struct file_system_type ** p;
INIT_LIST_HEAD(&fs->fs_supers);
write_lock(&file_systems_lock);
p = find_filesystem(fs->name, strlen(fs->name)); //1.1.1在全局变量file_system中查找
if (*p) //如果在全局变量中能够找到,*p!=NULL说明这个文件系统己经注册过了
res = -EBUSY;
else //如果在全局变量中不能找到,*p==NULL,说明这个文件系统没有注册可以使用
*p = fs; //使得file_systems.next=fs,链表中增加一项
write_unlock(&file_systems_lock);
return res;
}
1.1.1在全局变量文件系统类型的链表中查找有没有名字等于参数name的文件系统类型
static struct file_system_type **find_filesystem(const char *name, unsigned len)
{
struct file_system_type **p;
for (p=&file_systems; *p; p=&(*p)->next)
if (strlen((*p)->name) == len && //符合的条件是:名字与长度都相同
strncmp((*p)->name, name, len) == 0)
break;
return p;
}
2.在fs/namespace.c中
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); //2.1
ns = create_mnt_ns(mnt);
//为新的文件系统创建namespace
init_task.nsproxy->mnt_ns = ns;
get_mnt_ns(ns);
root.mnt = ns->root;
root.dentry = ns->root->mnt_root;
set_fs_pwd(current->fs, &root); //将进程0的当前路径设为rootfs的root
set_fs_root(current->fs, &root); //将进程0的fs设为rootfs的root
}
2.1在fs/namespace.c中
struct vfsmount * do_kern_mount(const char *fstype, int flags, const char *name, void *data)
{
//从全局变量file_systems中找出刚刚注册的"rootfs"的地址
struct file_system_type *type = get_fs_type(fstype);
struct vfsmount *mnt;
if (!type)
return ERR_PTR(-ENODEV);
mnt = vfs_kern_mount(type, flags, name, data); //2.1.1
put_filesystem(type); //空函数
return mnt;
}
2.1.1 rootfs的mount过程
在fs/namespace.c中
struct vfsmount * vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
{
struct vfsmount *mnt;
struct dentry *root;
if (!type)
return ERR_PTR(-ENODEV);
mnt = alloc_vfsmnt(name); //申请并初始化vfsmount结构体
//这儿flags==0
if (flags & MS_KERNMOUNT)
mnt->mnt_flags = MNT_INTERNAL;
root = mount_fs(type, flags, name, data); //2.1.2
mnt->mnt_root = root;
mnt->mnt_sb = root->d_sb;
mnt->mnt_mountpoint = mnt->mnt_root;
mnt->mnt_parent = mnt;
return mnt;
}
2.1.2调用具体文件系统的mount
在fs/super.c中
struct dentry * mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
{
struct dentry *root;
struct super_block *sb;
//file_system_type rootfs_fs_type 中定义.mount
= rootfs_mount,
root = type->mount(type, flags, name, data); //调用具体文件系统的mount
sb = root->d_sb;
sb->s_flags |= MS_BORN;
up_write(&sb->s_umount);
return root;
}
2.1.3在fs/ramfs/inode.c中
static struct dentry *rootfs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
return mount_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super);
}
2.1.4 在fs/super.c中
struct dentry *mount_nodev(struct file_system_type *fs_type, int flags, void *data,
int (*fill_super)(struct
super_block *, void *, int))
{
struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); //2.1.5
s->s_flags = flags;
error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); //2.1.6调用ramfs_fill_super,初始化super_block和root
s->s_flags |= MS_ACTIVE;
return dget(s->s_root); //获取在fill_super中初始化好的root
}
2.1.5 分配一个super_block并做初初化
struct super_block *sget(struct file_system_type *type,
int (*test)(struct
super_block *,void *),
int (*set)(struct
super_block *,void *),
void *data)
{
struct super_block *s = NULL;
struct super_block *old;
int err;
retry:
if (!s) {
s = alloc_super(type); //s是空的就需要分配一个super_block结构体
if (!s)
return ERR_PTR(-ENOMEM);
goto retry;
}
err = set(s, data);
s->s_type = type;
strlcpy(s->s_id, type->name, sizeof(s->s_id));
list_add_tail(&s->s_list, &super_blocks);
list_add(&s->s_instances, &type->fs_supers);
spin_unlock(&sb_lock);
get_filesystem(type);
return s;
}
2.1.6 初始化super_block并初始化root
int ramfs_fill_super(struct super_block *sb, void *data, int silent)
{
struct ramfs_fs_info *fsi;
struct inode *inode = NULL;
struct dentry *root;
int err;
save_mount_options(sb, data);
fsi = kzalloc(sizeof(struct ramfs_fs_info), GFP_KERNEL);
sb->s_fs_info = fsi;
err = ramfs_parse_options(data, &fsi->mount_opts);
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = RAMFS_MAGIC;
sb->s_op = &ramfs_ops;
sb->s_time_gran = 1;
//分配inode结构体并初始化inode->i_ino=1
inode = ramfs_get_inode(sb, NULL, S_IFDIR | fsi->mount_opts.mode, 0);
//初始化root的dentry结构体
root = d_alloc_root(inode);
sb->s_root = root;
return 0;
}
二. 真正的文件系统的挂载过程
系统开始时先挂载了一个临时的文件系统,通过这个临时的文件系统
init/main.c
start_kernel
{
vfs_caches_init(totalram_pages); ;在fs/dcache.c:创建一个虚拟的文件系统
--> mnt_init ;在fs/namespace.c中
--> init_rootfs ;1.在fs/ramfs/inode.c中
--> init_mount_tree(); ;2.在fs/namespace.c中
}
1.在fs/ramfs/inode.c中
int __init init_rootfs(void)
{
bdi_init(&ramfs_backing_dev_info); //初始化ramfs_backing_dev_info结构体
register_filesystem(&rootfs_fs_type); //1.1注册rootfs_fs_type,
} 即把rootfs_fs_type添加到全局变量中
static struct backing_dev_info ramfs_backing_dev_info = {
.name = "ramfs",
.ra_pages = 0, /* No
readahead */
.capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK |
BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |
BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,
};
static struct file_system_type rootfs_fs_type = {
.name = "rootfs",
.mount = rootfs_mount,
.kill_sb = kill_litter_super,
};
1.1全局变量file_systems链表中将参数fs添加进来
int register_filesystem(struct file_system_type * fs)
{
struct file_system_type ** p;
INIT_LIST_HEAD(&fs->fs_supers);
write_lock(&file_systems_lock);
p = find_filesystem(fs->name, strlen(fs->name)); //1.1.1在全局变量file_system中查找
if (*p) //如果在全局变量中能够找到,*p!=NULL说明这个文件系统己经注册过了
res = -EBUSY;
else //如果在全局变量中不能找到,*p==NULL,说明这个文件系统没有注册可以使用
*p = fs; //使得file_systems.next=fs,链表中增加一项
write_unlock(&file_systems_lock);
return res;
}
1.1.1在全局变量文件系统类型的链表中查找有没有名字等于参数name的文件系统类型
static struct file_system_type **find_filesystem(const char *name, unsigned len)
{
struct file_system_type **p;
for (p=&file_systems; *p; p=&(*p)->next)
if (strlen((*p)->name) == len && //符合的条件是:名字与长度都相同
strncmp((*p)->name, name, len) == 0)
break;
return p;
}
2.在fs/namespace.c中
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); //2.1
ns = create_mnt_ns(mnt);
//为新的文件系统创建namespace
init_task.nsproxy->mnt_ns = ns;
get_mnt_ns(ns);
root.mnt = ns->root;
root.dentry = ns->root->mnt_root;
set_fs_pwd(current->fs, &root); //将进程0的当前路径设为rootfs的root
set_fs_root(current->fs, &root); //将进程0的fs设为rootfs的root
}
2.1在fs/namespace.c中
struct vfsmount * do_kern_mount(const char *fstype, int flags, const char *name, void *data)
{
//从全局变量file_systems中找出刚刚注册的"rootfs"的地址
struct file_system_type *type = get_fs_type(fstype);
struct vfsmount *mnt;
if (!type)
return ERR_PTR(-ENODEV);
mnt = vfs_kern_mount(type, flags, name, data); //2.1.1
put_filesystem(type); //空函数
return mnt;
}
2.1.1 rootfs的mount过程
在fs/namespace.c中
struct vfsmount * vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
{
struct vfsmount *mnt;
struct dentry *root;
if (!type)
return ERR_PTR(-ENODEV);
mnt = alloc_vfsmnt(name); //申请并初始化vfsmount结构体
//这儿flags==0
if (flags & MS_KERNMOUNT)
mnt->mnt_flags = MNT_INTERNAL;
root = mount_fs(type, flags, name, data); //2.1.2
mnt->mnt_root = root;
mnt->mnt_sb = root->d_sb;
mnt->mnt_mountpoint = mnt->mnt_root;
mnt->mnt_parent = mnt;
return mnt;
}
2.1.2调用具体文件系统的mount
在fs/super.c中
struct dentry * mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
{
struct dentry *root;
struct super_block *sb;
//file_system_type rootfs_fs_type 中定义.mount
= rootfs_mount,
root = type->mount(type, flags, name, data); //调用具体文件系统的mount
sb = root->d_sb;
sb->s_flags |= MS_BORN;
up_write(&sb->s_umount);
return root;
}
2.1.3在fs/ramfs/inode.c中
static struct dentry *rootfs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
return mount_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super);
}
2.1.4 在fs/super.c中
struct dentry *mount_nodev(struct file_system_type *fs_type, int flags, void *data,
int (*fill_super)(struct
super_block *, void *, int))
{
struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); //2.1.5
s->s_flags = flags;
error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); //2.1.6调用ramfs_fill_super,初始化super_block和root
s->s_flags |= MS_ACTIVE;
return dget(s->s_root); //获取在fill_super中初始化好的root
}
2.1.5 分配一个super_block并做初初化
struct super_block *sget(struct file_system_type *type,
int (*test)(struct
super_block *,void *),
int (*set)(struct
super_block *,void *),
void *data)
{
struct super_block *s = NULL;
struct super_block *old;
int err;
retry:
if (!s) {
s = alloc_super(type); //s是空的就需要分配一个super_block结构体
if (!s)
return ERR_PTR(-ENOMEM);
goto retry;
}
err = set(s, data);
s->s_type = type;
strlcpy(s->s_id, type->name, sizeof(s->s_id));
list_add_tail(&s->s_list, &super_blocks);
list_add(&s->s_instances, &type->fs_supers);
spin_unlock(&sb_lock);
get_filesystem(type);
return s;
}
2.1.6 初始化super_block并初始化root
int ramfs_fill_super(struct super_block *sb, void *data, int silent)
{
struct ramfs_fs_info *fsi;
struct inode *inode = NULL;
struct dentry *root;
int err;
save_mount_options(sb, data);
fsi = kzalloc(sizeof(struct ramfs_fs_info), GFP_KERNEL);
sb->s_fs_info = fsi;
err = ramfs_parse_options(data, &fsi->mount_opts);
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = RAMFS_MAGIC;
sb->s_op = &ramfs_ops;
sb->s_time_gran = 1;
//分配inode结构体并初始化inode->i_ino=1
inode = ramfs_get_inode(sb, NULL, S_IFDIR | fsi->mount_opts.mode, 0);
//初始化root的dentry结构体
root = d_alloc_root(inode);
sb->s_root = root;
return 0;
}
二. 真正的文件系统的挂载过程
相关文章推荐
- Linux内核---42.arm 内存初始化2
- [CentOS7]安装mysql遇到的问题
- Linux内核---41.arm 内存初始化
- Linux内核---40.模块加载过程分析
- Linux内核---39.ELF 结构分析
- centos更新163源并升级内核
- Linux小知识
- linux常用命令
- 在linux使用make编译ArduPilot for Pixhawk/PX4 ArduPilot 编译环境搭建
- gcc: error: elf_i386: No such file or directory
- 橙子第一篇文章
- linux菜鸟学习(一)----ls,cd,pwd,mkdir,rmdir,rm
- centos yum升级php5.3.3到最5.6.3
- 【linux GDB】linux下GDB调试器_学习笔记_003
- centos安装php扩展mssql
- centos最常用命令及终端快捷键整理
- ELF文件分析
- CentOS系统内核升级
- Linux基础-----find和重定向命令
- linux下使用eclipse编辑,链接,使用动态库的学习笔记