u盘显示nofile (U盘显示无媒体) 层次分析文件系统

自上而下主要分为用户层,VFS层、文件系统层、缓存层、块设备层、磁盘驱动层、磁盘物理层

用户层:上述用户层是我们日常使用的各种程序,所需的接口主要是文件的创建、删除、打开、关闭、写作、阅读等。VFS层:我们知道Linux分为用户态和内核态,需要调用用户态要求的硬件资源System Call通过内核态实现。这些文件的相关操作对应System Call接口调用函数接口 VFS相应的函数。文件系统层:实现了不同的文件系统VFS这些函数通过指针注册VFS里面。因此,用户的操作是通过VFS转到各种文件系统。文件系统将文件读写命令转化为磁盘LBA操作起着翻译和磁盘管理的作用。缓存层:文件系统下有缓存,Page Cache,加速性能。对磁盘LBA此处缓存读写数据。块设备层:块设备接口Block Device用于访问磁盘LBA读写命令组合后,插入命令队列,磁盘驱动从队列读写命令执行。Linux电梯算法的设计等等LBA优化读写排序,尽量把连续地址放在一起。磁盘驱动层:磁盘驱动程序对LBA读写命令转化为各自的协议,如ATA命令,SCSI可以识别自己硬件的命令或自定义命令发送给磁盘控制器。Host Based SSD甚至在块设备层和磁盘驱动层也实现了FTL,变成对Flash芯片操作。磁盘物理层:向磁盘介质读写物理数据。

虚拟文件系统VFS

VFS其功能是利用标准系统调用不同物理介质上的不同文件系统。VFS可以让open()、read()、write()等系统调用粘合层,不用担心底层的存储介质和文件系统类型。在古老的DOS在操作系统中,需要特殊工具才能访问本地文件系统以外的文件系统。而在Linux下,通过VFS,抽象的通用访问接口屏蔽了底层文件系统和物理介质之间的差异。每种类型的文件系统代码都隐藏了实现的细节。因此,对于VFS对于层和内核的其他部分,每种类型的文件系统看起来都一样。

现在先了解一下VFS数据结构:虽然不同文件系统类型的物理结构不同,但虚拟文件系统定义了一套统一的数据结构:超快对象、索引节点对象、 目录对象、文件对象。

(1)超级块。文件系统的第一块是超级块,描述文件系统的整体信息,并在内存中创建超级块的副本。(2)挂载描述符。在内存中,虚拟文件系统将目录组织成一棵树。只有将文件系统挂载到内存中目录树的目录下,才能访问此文件系统。虚拟文件系统每次都会创建一个挂载描述符:mount 结构体,读取文件系统的超级块,在内存中创建超级块的副本。(3)文件系统类型。每个文件系统的超级块格式不同,需要向虚拟文件系统注册文件系统类型file_system_type,并且实现 mount 该方法用于读取和分析超级块。(4)索引节点。每个文件对应一个索引节点,每个索引节点都有一个唯一的编号。当内核访问存储设备上的文件时,会在内存中创建索引节点的副本:结构体 inode。(5)目录项。文件系统将目录视为文件的一种类型。目录的数据由目录项组成。每个目录项存储一个子目录或文件的名称和相应的索引节点号。当内核访问存储设备上的目录项时,会在内存中创建目录项的副本:结构体 dentry。(6)文件。当过程打开文件时,虚拟文件系统将创建一个打开文件的例子:file结构体,然后在打开过程的文件表中分配一个索引,称为文件描述符,最后将文件描述符和 file 在打开文件表中添加结构体的映射。1.超级块对象

超级块对象代表一个具体的已安装文件系统,通常是一个有超级块的分区。各种文件系统必须存储文件系统的信息并使用超级块对象struct super_block结构体表示,在include/linux/fs.h文件中

struct super_block{ struct list_head s_list; //超快链表头,指向所有超级块 dev_t s_dev; //设备号 unsigned char s_blocksize_bits;//块大小,单位为位 unsigned long s_blocksize;//块大小,单位为字节 loff_t s_maxbytes;//文件大小上限 struct file_system_type *s_type;//文件系统类型 const struct super_operations *s_op;///超级块操作方法函数 const struct dquot_operations *dq_op;///磁盘限额法函数 const struct quotactl_ops *s_qcop;/// const struct export_operations *s_export_op;///导出方法函数 unsigned long s_flags;//挂载标志位 unsigned long s_iflags;// unsigned long s_magic;//文件系统的魔数,每个文件系统类型分配一个唯一的魔法数 struct dentry *s_root;//目录挂载点 struct rw_semaphore s_umount;///卸载信号量 int s_count;///超级块引用计数 atomic_t s_active;//活动引用计数#ifdef CONFIG_SECURITY void *s_security;///指向安全模块#endif const struct xattr_handler **s_xattr;///扩展属性#if IS_ENABLED(CONFIG_FS_ENCRYPTION) const struct fscrypt_operations *s_cop;//文件加密方法函数#endif struct hlist_bl_head s_roots; /* alternate root dentries for NFS */ struct list_head s_mounts; /* list of mounts; _not_ for fs use */ struct block_device *s_bdev;///相关块设备 struct backing_dev_info *s_bdi; struct mtd_info *s_mtd;//存储磁盘信息 ///链接同一文件系统类型的所有超级块实例,链表的头节点是结构体file_system_type的成员fs_supers struct hlist_node s_instances; unsigned int s_quota_types; /* Bitmask of supported quota types */ struct quota_info s_dquot;/// struct sb_writers s_writers;//超级块使用信息 char s_id[32];/超级块名,也是分区名 uuid_t s_uuid; /* UUID */ void *s_fs_info;////文件系统私有信息 unsigned int s_max_links;//文件链接上限 fmode_t s_mode;///安装权限 /* Granularity of c/m/atime in ns. Cannot be worse than a second */ u32 s_time_gran;///文件访问修改时间的最小单位 /* * The next field is for VFS *only*. No filesystems have any business * even looking at it. You had been warned. */ struct mutex s_vfs_rename_mutex; /* Kludge */ /* * Filesystem subtype. If non-empty the filesystem type field * in /proc/mounts will be "type.subtype" */ char *s_subtype;///文件系统子类型 const struct dentry_operations *s_d_op; ///默认超级块目录操作方法函数 /* * Saved pool identifier for cleancache (-1 means none) */ int cleancache_poolid;//保存池标识符 ... /* * Owning user namespace and default context in which to * interpret filesystem uids, gids, quotas, device nodes, * xattrs and security labels. */ struct user_namespace *s_user_ns;//拥有者 /* * Keep the lru lists last in the structure so they always sit on their * own individual cachelines. */ struct list_lru s_dentry_lru ____cacheline_aligned_in_smp;///最近最少使用的目录链表 struct list_lru s_inode_lru ____cacheline_aligned_in_smp;///最近最少使用的文件链表 struct rcu_head rcu; struct work_struct destroy_work; struct mutex s_sync_lock; /* sync serialisation lock */ /* * Indicates how deep in a filesystem stack this SB is */ int s_stack_depth;///指示文件系统堆栈中超级块的深度 /* s_inode_list_lock protects s_inodes */ spinlock_t s_inode_list_lock ____cacheline_aligned_in_smp;//超级块锁 struct list_head s_inodes;///超级块中所有文件的链表 spinlock_t s_inode_wblist_lock;//回写所需的锁 struct list_head s_inodes_wb;///需要回写的文件链表}__randomize_layout;

超级块对象中最重要的是成员const struct super_operations *s_op;这是超级块操作方法函数:

struct super_operations{ struct inode *(*alloc_inode)(struct super_block *sb);///创建和初始化新的索引节点 void (*destroy_inode)(struct inode *);///释放索引节点