文件系统浅析

文件系统浅析

一、文件系统定义

    什么是文件系统?按照维基百科定义:即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。
    简单来说,文件系统可以理解成一种将flash(磁盘)抽象成文件夹,供上层用户管理和使用的机制。

1.1 文件系统框架

    以linux系统为例,操作系统在初始化的时候就要初始化文件系统,将flash(硬盘)里面存储的数据mount成文件系统。那么初始化文件系统又是值什么呢?

    实际文件系统维护的就是一个super_block块,这个super_block块里面会记录我们创建的文件信息,如文件名、文件链接数、inode以及在flash中的存储位置等信息。此外,它也存在自己的备份机制。以ext3文件系统为例。

struct ext3_super_block {
	unsigned int s_inodes_count;      /* inodes 计数 */
	unsigned int s_blocks_count;      /* blocks 计数 */
	unsigned int s_r_blocks_count;    /* 保留的 blocks 计数 */
	unsigned int s_free_blocks_count; /* 空闲的 blocks 计数 */
	unsigned int s_free_inodes_count; /* 空闲的 inodes 计数 */
	unsigned int s_first_data_block;  /* 第一个数据 block */
	unsigned int s_log_block_size;    /* block 的大小 */
	signed int s_log_frag_size;     /* 可以忽略 */
	unsigned int __u32 s_blocks_per_group;  /* 每 block group 的 block 数量 */
	unsigned int s_frags_per_group;   /* 可以忽略 */
	unsigned int s_inodes_per_group;  /* 每 block group 的 inode 数量 */
	unsigned int s_mtime;             /* Mount time */
	unsigned int s_wtime;             /* Write time */
	unsigned short s_mnt_count;         /* Mount count */
	signed short s_max_mnt_count;     /* Maximal mount count */
	unsigned short s_magic;             /* Magic 签名 */
	unsigned short s_state;             /* File system state */
	unsigned short s_errors;            /* Behaviour when detecting errors */
	unsigned short s_minor_rev_level;   /* minor revision level */
	unsigned int s_lastcheck;         /* time of last check */
	unsigned int s_checkinterval;     /* max. time between checks */
	unsigned int s_creator_os;        /* 可以忽略 */
	unsigned int s_rev_level;         /* Revision level */
	unsigned short s_def_resuid;        /* Default uid for reserved blocks */
	unsigned short s_def_resgid;        /* Default gid for reserved blocks */
	unsigned int s_first_ino;         /* First non-reserved inode */
	unsigned short s_inode_size;        /* size of inode structure */
	unsigned short s_block_group_nr;    /* block group # of this superblock */
	unsigned int s_feature_compat;    /* compatible feature set */
	unsigned int s_feature_incompat;  /* incompatible feature set */
	unsigned int s_feature_ro_compat; /* readonly-compatible feature set */
	unsigned char  s_uuid[16];          /* 128-bit uuid for volume */
	unsigned char  s_volume_name[16];   /* volume name */
	unsigned char  s_last_mounted[64];  /* directory where last mounted */
	unsigned int s_algorithm_usage_bitmap; /* 可以忽略 */
	unsigned char  s_prealloc_blocks;        /* 可以忽略 */
	unsigned char  s_prealloc_dir_blocks;    /* 可以忽略 */
	unsigned short s_padding1;               /* 可以忽略 */
	unsigned char __u8  s_journal_uuid[16]; /* uuid of journal superblock */
	unsigned int s_journal_inum;     /* 日志文件的 inode 号数 */
	unsigned int s_journal_dev;      /* 日志文件的设备号 */
	unsigned int s_last_orphan;      /* start of list of inodes to delete */
	unsigned int s_reserved[197];    /* 可以忽略 */
};
1.1.1 单文件读取

    以下将介绍单个文件读写方式。从图中可以看出,在linux中对单个文件的操作是先去找到文件的inode节点信息,然后在通过super_block上查找到对应inode的block数据块,进而获取文件内容。
在这里插入图片描述

1.1.2 文件夹下文件读取

    针对文件夹里面的文件,则是需要先找到文件夹的inode,从inode对应的block中找到记录文件夹内文件的indoe,进而再重复上述单文件流程。因此文件存储越深,理论上需要IO的次数就越多。因此,为解决IO耗时问题,文件系统引入了d_entry的数据结构,对文件进行管理。
注:d_entry只有在对文件进行操作过一次后才会维护本文件的数据结构,因此对外体现就是首次打开文件慢,后续再次打开KPI明显降低。
在这里插入图片描述

1.1.3 d_entry数据结构

     为提高多级文件索引效率,文件系统中引入了d_entry的数据结构,对文件的属性进行管理。它记录文件的名称,父目录,子目录等信息,形成我们看到的层级树状结构。与inode不同的是,dentry只存在于内存,flash(磁盘)上并没有对应的实体文件,因此目录项也就不会涉及回写磁盘。因此极大的降低了多级目录下读取文件的IO次数
在这里插入图片描述

     通常文件系统在创建文件时(mkdir/touch)时便会去查找和创建一个d_entry。

long do_mkdirat(int dfd, const char __user *pathname, umode_t mode)
{
	//为该目录创建dentry
	dentry = user_path_create(dfd, pathname, &path, lookup_flags);
	...//省略
	if (!error)
		//调用对应文件系统的mkdir为该目录创建inode,对于ext4调用的是ext4_mkdir
		error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
	...
}
struct dentry {
	/* RCU lookup touched fields */
	unsigned int d_flags;		/* protected by d_lock */
	seqcount_t d_seq;		/* per dentry seqlock */
	struct hlist_bl_node d_hash; //通过该变量挂载到全局dentry哈希表dentry_hashtable上
	struct dentry *d_parent;	//父目录的目录项对象
	struct qstr d_name;         //目录项名称
	struct inode *d_inode;		//指向目录对应的inode结构
	unsigned char d_iname[DNAME_INLINE_LEN];	//存放短文件名

	struct lockref d_lockref;	//使用计数
	const struct dentry_operations *d_op; //目录项的操作函数
	struct super_block *d_sb;	//目录项对应的超级块
	unsigned long d_time;		/* used by d_revalidate */
	void *d_fsdata;			//文件系统私有数据

	union {
		struct list_head d_lru;		//通过该变量链接到超级块的s_dentry_lru链表
		wait_queue_head_t *d_wait;	/* in-lookup ones only */
	};
	struct list_head d_child;	//通过该变量链接到父目录的d_subdirs中
	struct list_head d_subdirs;	//本目录所有子目录链表

	union {
		//通过该变量链接到inode结构的i_dentry中,
		//一个inode可对应多个dentry,因为存在软链接
		struct hlist_node d_alias;	
		struct hlist_bl_node d_in_lookup_hash;	/* only for in-lookup ones */
	 	struct rcu_head d_rcu;
	} d_u;
};
1.2 虚拟文件系统VFS

    VFS从代码角度来说,是为适配各种文件系统,从而做的一层抽象。像上述中的d_entry也是属于在VFS构建。同样,VFS也有自己的super_block,由于每种文件系统的超级块的格式不同,因此需要向虚拟文件系统注册文件系统类型file_system_type,并且实现 mount 方法用来读取和解析超级块。

 struct super_block {
    struct list_head    s_list;        /* Keep this first 指向超级块链表的指针*/
    dev_t         s_dev;        /*具体文件系统的块设备描述符*/
    unsigned char s_blocksize_bits;
    unsigned long s_blocksize; /*以字节为单位的数据块的大小*/
    loff_t        s_maxbytes;    /* Max file size */
    struct file_system_type    *s_type; /*文件系统类型,每个文件系统只有一个结构体*/
    const struct super_operations    *s_op; /*指向super_block操作的函数集合*/
	alloc_inode () /*创建并初始化一个inode*/
	write_inode() /*将inode同步到磁盘*/
    sync_fs() /*同步文件系统元数据到磁盘*/      
    list_head s_inodes;  /* all inodes */
    list_head  s_inodess_dirty;  /* dirty inodes */
    void *s_fs_info;    /* Filesystem private info 具体文件系统的私有数据*/
    }
1.2.1 文件系统类型

常见的文件系统类型用如下几种。
按磁盘划分:ext3、ext4、XFS、NTFS、APFS
闪存(flash)和SSD:FAT、exFAT、jffs2
NAS:NFS、SMB、AFP(存储与服务器分离)

1.2.2 虚拟文件系统架构

    
在这里插入图片描述

参考链接:
https://blog.csdn.net/u010039418/article/details/115254325
https://blog.csdn.net/u010039418/article/details/114806339

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值