转自:https://blog.csdn.net/wuu1010/article/details/94332319
文章目录
1. mount系统调用
1.1. sys_mount
sys_mount主要将系统调用的参数dev_name、dir_name、type、flags、data从用户空间拷贝到内核空间,然后调用do_mount函数
sys_mount
copy_mount_string
copy_mount_options
do_mount
user_path(dirname, &path) -> path_lookupat ==> 复杂的过程,找到目录对应的挂载描述符合dentry实例
do_remount
do_loopback
do_change_type
do_move_mount
do_new_mount // 构建虚拟挂载点vsfmount,检查设置namespace
get_fs_type // 根据文件系统类型的命长找到file_system_type实例
vfs_kernel_mount // 调用具体文件系统的mount,并将返回的root dentry与分配的vfsmount挂接
alloc_vfsmnt // 分配挂载描述符
mount_fs
type->mount // 调用具体文件系统的mount,返回root dentry
设置vfsmount结构内容
把挂载描述符添加到长几块的挂载实例链表中
do_add_mount
graft_tree
attach_recursive_mnt
commit_tree
__attach_mnt
把挂载描述符加入散列表
把挂载描述符加入父亲的孩子列表
SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
char __user *, type, unsigned long, flags, void __user *, data)
{
int ret;
char *kernel_type;
char *kernel_dev;
void *options;
kernel_type = copy_mount_string(type);
ret = PTR_ERR(kernel_type);
if (IS_ERR(kernel_type))
goto out_type;
kernel_dev = copy_mount_string(dev_name);
ret = PTR_ERR(kernel_dev);
if (IS_ERR(kernel_dev))
goto out_dev;
options = copy_mount_options(data);
ret = PTR_ERR(options);
if (IS_ERR(options))
goto out_data;
ret = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
kfree(options);
out_data:
kfree(kernel_dev);
out_dev:
kfree(kernel_type);
out_type:
return ret;
}
1.2. ext4文件系统的mount
在mount_fs中通过下边语句调用特定文件系统的mount函数。
root = type->mount(type, flags, name, data);
- 1
static struct file_system_type ext4_fs_type = {
.owner = THIS_MODULE,
.name = "ext4",
.mount = ext4_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data)
{
return mount_bdev(fs_type, flags, dev_name, data, ext4_fill_super);
}
- 1
- 2
- 3
- 4
- 5
mount_bdev是针对块设备挂载时使用的函数,此外还有mount_nodev, mount_single等函数,分别用于不同的挂载情况。
mount_bdev函数的主要逻辑如下:
- blkdev_get_by_path根据设备名得到block_device结构
- sget得到已经存在或者新分配的super_block结构
- 如果是已经存在的sb,就释放第一步得到的bdev结构
- 如果是新的sb,就调用文件系统个别实现的fill_super函数继续处理新的sb,并创建根inode, dentry
- 返回得到的s_root
- fill_super函数将完成mount接下来重要的工作
1.4. ext4_fill_super
在磁盘挂载的时候文件系统需要从磁盘中读取超级块来填充内存中的结构,EXT4文件系统超级块的填充是由函数ext4_fill_super()来完成的。在EXT4文件系统中,磁盘上的超级块结构是与结构体structext4_super_block的定义是一致的,大小是1K,即1024个字节。顺便提下,EXT3文件系统超级块在磁盘上的大小也是1024个字节,EXT4扩展了EXT3的定义,EXT3只是占了1024个字节,有些字节没有定义,在EXT4中重新定义了,总的大小没有改变。
在挂载文件系统的时候,读取磁盘上ext4_super_block结构的值,填充内存中ext4_sb_info的结构。
2. 挂载根文件系统
start_kernel
vfs_caches_init
mnt_init
init_rootfs // 注册rootfs文件系统
init_mount_tree // 挂载rootfs文件系统
- 1
- 2
- 3
- 4
- 5
2.1. init_rootfs
init_rootfs注册rootfs文件系统
static struct file_system_type rootfs_fs_type = {
.name = "rootfs",
.mount = rootfs_mount,
.kill_sb = kill_litter_super,
};
int __init init_rootfs(void)
{
int err = register_filesystem(&rootfs_fs_type);
if (err)
return err;
if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] &&
(!root_fs_names || strstr(root_fs_names, "tmpfs"))) {
err = shmem_init();
is_tmpfs = true;
} else {
err = init_ramfs_fs();
}
if (err)
unregister_filesystem(&rootfs_fs_type);
return err;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
2.2. init_mount_tree
static void __init init_mount_tree(void)
{
struct vfsmount *mnt;
struct mnt_namespace *ns;
struct path root;
struct file_system_type *type;
type = get_fs_type("rootfs");
if (!type)
panic("Can't find rootfs type");
mnt = vfs_kern_mount(type, 0, "rootfs", NULL); // 挂载rootfs文件系统
put_filesystem(type);
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; // 设置0号线程的挂载命名工具
get_mnt_ns(ns);
root.mnt = mnt;
root.dentry = mnt->mnt_root;
mnt->mnt_flags |= MNT_LOCKED;
set_fs_pwd(current->fs, &root); // 把0号线程的当前工作目录设置为rootfs文件系统的根目录
set_fs_root(current->fs, &root); // 把0号线程的根目录设置为rootfs文件系统的根目录
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29