1.VFS操作对象
VFS的主要操作对象与结构包括file、inode、superblock、dentry。
Superblock表示被挂载的文件系统实例,包含存储设备、inode指针、块大小、superblock操作、文件系统类型、文件系统信息等。在一般文件系统中,它是存储于硬盘中文件系统控制块(filesystem control block)。
在VFS中inode储存了具体文件(目录)的相关信息,其中最重要的就是它们在具体文件系统内的inode编号,在用户空间可通过命令“ls-i”查看。很多文件系统比如ext系列、XFS等,都存在inode数据结构。
Dentry则是文件系统中目录与文件的映射关系,这种关系根据文件系统类型不同而有所差异。
与用户空间进程文件描述符(fd)对应的就是VFS中的file对象,它被存储于内核空间中且随着用户空间进程成功关闭文件而被释放。
2.VFS中涉及的主要操作形式
□文件系统类型注册
在使用某种文件系统时,内核首先需要将其注册至VFS。通常这个过程发生在系统启动或者手动加载文件系统模块时,注册完成后内核会将与之对应的file_system_type对象加入一个含有多种文件系统类型对象的单向链表中。
□挂载文件系统
在类Unix系统中,很多文件系统都可以通过形似“mount-t ext4/dev/sdb/mnt/sdb”的命令进行挂载,并且可以多次挂载到不同的挂载点。(https://www.xing528.com)
挂载普通文件系统时,一般会使用系统调用mount()作为开始,然后再相继调用一系列内核函数。期间的do_kern_mount()函数会通过get_fs_type()、allocl_vfsmnt()、get_sb获取挂载点与文件系统的superblock信息,然后再调用mnt_sb()、mnt_root()等函数进行挂载。
挂载根文件系统的过程发生在系统初始化的时候,由于要支持多种文件系统作为挂载点,所以相对来说它比较复杂,其过程可以简单分为两个部分。首先内核挂载会首先挂载一个特殊的rootfs文件系统,然后将其作为真正根文件系统的挂载点以挂载系统根目录,调用sys_chroot()后执行路径指向真正的根文件系统。
□卸载文件系统
系统调用umount()用于卸载已挂载的文件系统,命令形似“umount/mnt/sdb”或者“umount/dev/sdb”。这个过程中内核会释放superblock并减少信号灯的值(因为一个文件系统可以被挂载多次,所以我们需要在卸载时对其是否存在其他挂载点进行检查)。对于存在读写进程的挂载点来说,在卸载时内核一般会检查其中的文件锁以阻止卸载。
□解析文件路径名
所有与文件或者目录相关的操作内核都要在VFS中对其路径名进行解析,以向其调用者返回正确的inode。在解析时,会对文件的权限、文件形式(符号链接、目录)、所处命名空间(参考第五章内容)等进行检查。具体解析操作是由path_lookup()函数完成,期间会查找dentry中d_inode(代表目录的inode),如果路径名中存在“.”、“..”,则在处理时分别予以跳过或者进入父目录。
□实现文件相关系统调用
VFS在内核中注册的系统调用主要包括open()、read()、write()、close()等,它们与上层应用程序需要的文件描述符紧密相关。
□文件锁
绝大多数编程语言的文件锁实现,包括建议锁(advisory lock)、强制锁(mandatory lock),即是以VFS提供的fcntl()和flock()为基础。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。
