Linux kernel 如何在挂载的时候确定具体文件系统类型
本文通过分析内核挂载和初始化源码剖析内核是如何知道调用的是具体哪个文件系统的函数。
一:文件系统注册结构体函数(参考:https://books.google.co.jp/books?id=h0lltXyJ8aIC&pg=PT498&lpg=PT498&dq=struct+file_system_type&source=bl&ots=gP5rKV8fKT&sig=ACfU3U0GOHI4xtDWlFbLBKh6G8swkzA-ig&hl=en&sa=X&ved=2ahUKEwjd_rnI85fkAhXpxYsBHVneC6k4ChDoATAGegQICBAB#v=onepage&q=struct%20file_system_type&f=false)
先来看两个函数
在系统初始化时,register_filesystem() 函数在编译内核时被调用给每个指定的文件系统;该函数插入file_system_type对象到filesystem-type列表中。
该函数也可以在一个模块实现一个文件系统被加载时调用(意思大概就是我们可以手动加载一个模块,该模块是实现一个文件系统时可以被调用)。这种情况下文件系统也可以在卸载模块是被取消注册(通过调用unregister_filesystem函数)。
二、挂载流程
1. 关于mount参数详解可以参考这里:https://linux.die.net/man/8/mount
重点: 如果没有指定-t选项,或者是制定了auto类型,mount将尝试去猜测期望的类型。Mount使用blkid或者volume_id库去猜测文件系统类型。如果这样还是没找到相似的,mount将尝试去读取文件/etc/filesystems,或者如果该文件不存在,就读取/proc/filesystems文件。在文件里面列出的所有的文件系统类型将会被尝试,除了那些被打有“nodev"标签的(比如 devpts,proc和nfs),可能是灾难性的结果,因此如果你的数据是有价值的,还是别让mount去猜测了。
攒满假设讨论制定了-t ext4 的挂载,那么该类型字符串会从用户空间拷贝到内核空间中往下传递。
2. ksys_mount
->do_mount
->do_new_mount
->get_fs_type
->fs_context_for_mount
->do_new_mount_fc
->vfs_create_mount(fc)
->do_add_mount
(1) 函数get_fs_type接收一个文件系统名称作为它的参数,扫描已经注册的文件系统列表,查看字段并且返回对应于file_system_type对象的指针。
// 在file_systems链表中查找是否能找到一个已经注册的文件系统类型
//找到的话返回该file_system_type
static struct file_system_type *__get_fs_type(const char *name, int len)
{struct file_system_type *fs;read_lock(&file_systems_lock);fs = *(find_filesystem(name, len));if (fs && !try_module_get(fs->owner))fs = NULL;read_unlock(&file_systems_lock);return fs;
}
(2)重点函数fs_context_for_mount
fc = fs_context_for_mount(type, sb_flags);
(1)vfs_create_mount函数主要是调用alloc_vfsmnt 分配一个新的挂载的文件系统描述符,且做一些初始化。
struct vfsmount *vfs_create_mount(struct fs_context *fc)
{struct mount *mnt;if (!fc->root)return ERR_PTR(-EINVAL);mnt = alloc_vfsmnt(fc->source ?: "none");//分配一个struct mount结构if (!mnt)return ERR_PTR(-ENOMEM);if (fc->sb_flags & SB_KERNMOUNT)mnt->mnt.mnt_flags = MNT_INTERNAL;//初始化 mnt中的struct vfsmount结构atomic_inc(&fc->root->d_sb->s_active);mnt->mnt.mnt_sb = fc->root->d_sb; // 超级块结构mnt->mnt.mnt_root = dget(fc->root);mnt->mnt_mountpoint = mnt->mnt.mnt_root;mnt->mnt_parent = mnt;lock_mount_hash();list_add_tail(&mnt->mnt_instance, &mnt->mnt.mnt_sb->s_mounts);unlock_mount_hash();return &mnt->mnt;
}
struct vfsmount {struct dentry *mnt_root; /* root of the mounted tree */struct super_block *mnt_sb; /* pointer to superblock */int mnt_flags;
} __randomize_layout;
(2).do_add_mount 将新的挂载文件系统对象插如到namespace list中
(三)
其实有一个问题,我一直很好奇到底对于具体的某个文件系统内核怎么知道在挂载的时候要去调用ext4对应的函数,虽然你在mount的时候传递了ext4 类型进来。 就比如说怎么知道是调用的ext4_fill_super 而不是其它类型的文件系统。
就是我们知道比如对于ext4文件系统回在系统加载内核启动的时候注册file_system_type 是属于ext4的。
在fs/ext4/super.c文件最下面注册了ext4模块
MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
MODULE_DESCRIPTION("Fourth Extended Filesystem");
MODULE_LICENSE("GPL");
MODULE_SOFTDEP("pre: crc32c");
module_init(ext4_init_fs)
module_exit(ext4_exit_fs)
函数ext4_init_fs里调用了err = register_filesystem(&ext4_fs_type);
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,
};
MODULE_ALIAS_FS("ext4");
重点来了,就是这里挂载的时候传入了ext4_file_super
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);
}
在ext4_file_super函数后面会指定操作函数
sbi->s_stripe = ext4_get_stripe_size(sbi);sbi->s_extent_max_zeroout_kb = 32;/** set up enough so that it can read an inode*/sb->s_op = &ext4_sops;sb->s_export_op = &ext4_export_ops;sb->s_xattr = ext4_xattr_handlers;
static const struct super_operations ext4_sops = {.alloc_inode = ext4_alloc_inode,.free_inode = ext4_free_in_core_inode,.destroy_inode = ext4_destroy_inode,.write_inode = ext4_write_inode,.dirty_inode = ext4_dirty_inode,.drop_inode = ext4_drop_inode,.evict_inode = ext4_evict_inode,.put_super = ext4_put_super,.sync_fs = ext4_sync_fs,.freeze_fs = ext4_freeze,.unfreeze_fs = ext4_unfreeze,.statfs = ext4_statfs,.remount_fs = ext4_remount,.show_options = ext4_show_options,
#ifdef CONFIG_QUOTA.quota_read = ext4_quota_read,.quota_write = ext4_quota_write,.get_dquots = ext4_get_dquots,
#endif.bdev_try_to_free_page = bdev_try_to_free_page,
};
更加详细的内容不做分析。
Linux kernel 如何在挂载的时候确定具体文件系统类型相关推荐
- linux img提取文件系统,Linux下 mount IMG文件提示“您必须制定文件系统类型”解决方法...
以Ubuntu 12.04为例: 假设我有个文件test.img,要挂载到/mnt/img文件目录下: 操作如下: $ cd "你的img镜像所在目录" $ losetup /de ...
- linux下 mount IMG文件提示“您必须指定文件系统类型”
在做实验关于Qt raspberry时 https://wiki.qt.io/Raspberry_Pi_Beginners_Guide 解析命令知识点 1.loop 设备 在类 UNIX 系统里,lo ...
- linux分布式文件存储挂载使用_Linux - tmpfs内存文件系统使用
简介 tmpfs是一种虚拟内存文件系统,而不是块设备.是基于内存的文件系统,创建时不需要使用mkfs等初始化. 由于都是在内存里面,所以重启之后,数据就会都没掉,但是在内存里面就有好处,速度快,因此现 ...
- linux磁盘分区,挂载,及查看
1.磁盘的分区主要分为基本分区(primary partion)和扩充分区(extension partion)两种,基本分区和扩充分区的数目之和不能大于四个.且基本分区可以马上被使用但不能再分区.扩 ...
- Linux基础知识之挂载详解(mount,umount及开机自动挂载)
挂载概念简述: 根文件系统之外的其他文件要想能够被访问,都必须通过"关联"至根文件系统上的某个目录来实现,此关联操作即为"挂载",此目录即为"挂载点& ...
- [转载]Linux基础知识之挂载详解(mount,umount及开机自动挂载)
挂载概念简述: 根文件系统之外的其他文件要想能够被访问,都必须通过"关联"至根文件系统上的某个目录来实现,此关联操作即为"挂载",此目录即为"挂载点& ...
- Linux Kernel 3.0新特性概览(转)
上周五,Linus Torvalds终于发布了备受瞩目的新一代Linux操作系统内核.Linux Kernel 3.0经过了七个RC候选版才推出正式版本,上一个版本是5月19日的2.6.39,也是2. ...
- Linux磁盘管理——分区+挂载(fdisk+gdisk+mount+lsblk+df)
文章目录 一.硬盘基础知识 1. 硬盘命名方式 2. 磁盘设备的命名 3. 硬盘的分区方式 二.基本分区管理 1. 磁盘划分思路 2.lsblk命令 3. df 命令 4. fdisk 1)进入分区 ...
- linux主分区移动挂载,Linux磁盘分区和挂载
Linux磁盘分区和挂载 分区 分区的方式: mbr分区 最多支持4个主分区 系统只能安装到主分区上 扩展分区要占用一个主分区 MBR最大支持2TB,但拥有最好的兼容性 gtp分区 支持无线多个主分区 ...
最新文章
- html canvas text 居中,HTML5 Canvas Text文本居中实例
- 只会python好找工作吗-转行去培训班学Python好找工作吗?老男孩教育
- STM32 基础系列教程 3 – 外部中断
- BZOJ4388 : JOI2012 invitation
- 网络爬虫--10.使用正则表达式的爬虫
- CSS串联和后代选择器
- python推荐_利用Python构建一个简单的推荐系统
- 小牛485通讯原理_plc和变频器通讯接线图详解
- axure 发布 主页_车队如何在黑鸟APP发布同城活动?教程来了!
- Python爬虫之一键保存全部必应高清1080P壁纸
- linux总线控制设备,在platform总线上注册设备并载入驱动控制led灯
- querySelector()与querySelectorAll()
- Julia:从交易流水动态计算可用资金
- c语言单片机期末试题及答案,单片机原理与应用期末试题及答案
- 三种css样式应用方式,CSS样式三种形式
- 最小二乘拟合问题求解算法(含python代码)
- python商务图表_Excel 数据之美:科学图表与商业图表的绘制(全彩)
- X_Forward_For(XXF)获取用户IP
- Easy3D 孔洞修补
- 配置文件加密(Jasypt的简单使用)