文件系统即对文件存储器空间进行组织和分配。
linux采用树状结构,最上层为根目录,而其他所有目录都从根目录出发,即只有一棵树,而DOS和Windows则不同,其也是树状结构但最上层为磁盘分区的盘符,即有多少分区则有多少棵树。linux这样设计有助于对其多用户下的系统文件及用户文件进行管理
为了linux的开放性,设计人员必须将不同文件系统的操作和管理纳入统一的框架,于是虚拟文件系统(VFS)就为此而生,其实际上是一组系统调用,但是能够对各种不同的文件系统及文件进行操作
linux VFS核心数据结构:
linux中实现文件系统的核心就是其所用到的各种数据结构,主要有4种:索引节点、超级块、目录项及文件对象
1、索引节点(inode):
索引节点包含了一个文件的所有信息,当文件系统要对一个文件进行操作时,主要依靠inode数据结构来提供信息
我们可以通过stat 文件名
来查看某一个文件的inode信息
struct inode { /*文件索引节点*/
struct hlist_node i_hash; /*哈希表*/
struct list_head i_list; /* backing dev IO list */ /*索引节点的链表*/
struct list_head i_sb_list; /*超级块链表*/
struct list_head i_dentry; /*目录项链表*/
unsigned long i_ino; /*文件节点号,唯一表示一个文件系统中的一个文件*/
atomic_t i_count; /*引用计数*/
unsigned int i_nlink; /*文件的硬链接数*/
uid_t i_uid; /*拥有者id*/
gid_t i_gid; /*拥有组id*/
dev_t i_rdev; /*设备标识符*/
u64 i_version; /*版本号*/
loff_t i_size; /*文件大小,以字节为单位*/
#ifdef __NEED_I_SIZE_ORDERED
seqcount_t i_size_seqcount; /*对i_size进行串行计数*/
#endif
struct timespec i_atime; /*文件最后一次被访问的时间*/
struct timespec i_mtime; /*文件最后一次被修改的时间*/
struct timespec i_ctime; /*文件的inode被修改的时间*/
blkcnt_t i_blocks; /*文件所占的块数*/
unsigned int i_blkbits; /*块的大小,单位是位*/
unsigned short i_bytes; /*用的字节数*/
umode_t i_mode; /*访问的权限*/
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
struct mutex i_mutex;
struct rw_semaphore i_alloc_sem;
const struct inode_operations *i_op; /*索引节点的操作表*/
const struct file_operations *i_fop; /* former ->i_op->default_file_ops */
struct super_block *i_sb; /*与此索引节点相关的超级块*/
struct file_lock *i_flock;
struct address_space *i_mapping; /*地址映射*/
struct address_space i_data; /*设备地址映射*/
...
struct list_head i_devices;
union {
struct pipe_inode_info *i_pipe; /*如果此文件是一个管道,记录管道信息*/
struct block_device *i_bdev; /*指向块设备驱动程序*/
struct cdev *i_cdev; /*指向字符设备驱动程序*/
};
...
unsigned long i_state; /*inde的状态标识符*/
unsigned long dirtied_when; /* jiffies of first dirtying */
unsigned int i_flags; /*文件系统标志*/
atomic_t i_writecount; /*写者计数*/
...
};
可以看到里面基本包含了所有关于文件的信息,不过却没有文件名,这是跟linux中的符号链接有关,在后面进行解释,不过正是因为这种索引节点号与文件名分离的设计,导致一些Linux中的特殊情况:
1. 文件名包含特殊字符,无法正常删除时,直接删除inode节点,就能起到删除文件的作用。
2. 移动文件或重命名文件,只是改变文件名,不影响inode号码。
3. 打开一个文件以后,系统就以inode号码来识别这个文件,不再考虑文件名。因此,通常来说,系统无法从inode号码得知文件名。
inode会消耗硬盘空间,所以硬盘格式化的时候,操作系统自动将硬盘分成两个区域。一个是数据区,存放文件数据;另一个是inode区(inode table),存放inode所包含的信息。
查看每个硬盘分区的inode总数和已经使用的数量,可以使用df命令df -i
由于每个文件都必须有一个inode,因此有可能发生inode已经用光,但是硬盘还未存满的情况。这时,就无法在硬盘上创建新文件。
当我们通过文件名来打开文件时,基本分为3步:1、根据文件名找到对应的索引节点号;2、根据索引节点号找到对应的inode结构;3、根据inode中的信息找到对应的block,读出数据。
我们可以通过ls -i 文件名
来查看一个文件的inode号
2、超级块(super_block)
超级块是用来描述文件系统的信息,对于每个文件系统都有其自己的超级块,其在文件系统安装时建立,在文件系统卸载时自动删除