博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
文件系统重要的数据结构
阅读量:4993 次
发布时间:2019-06-12

本文共 7175 字,大约阅读时间需要 23 分钟。

super_block:存放已安装文件系统的信息;记录此 filesystem 的整体信息,包括inode/block的总量、使用量、剩余量,以及文件系统的格式不相关信息等

struct super_block {	struct list_head	s_list;		/* Keep this first */	dev_t			s_dev;		/* search index; _not_ kdev_t */	unsigned long		s_blocksize;	unsigned char		s_blocksize_bits;	unsigned char		s_dirt;	unsigned long long	s_maxbytes;	/* Max file size */	struct file_system_type	*s_type;    //文件系统类型	const struct super_operations	*s_op; //超级块操作,主要是对inode和super_block进行操作	struct dquot_operations	*dq_op; 	struct quotactl_ops	*s_qcop;	const struct export_operations *s_export_op;	unsigned long		s_flags;	unsigned long		s_magic;	struct dentry		*s_root; // 文件系统根目录的目录项	struct rw_semaphore	s_umount;	struct mutex		s_lock;	int			s_count;	int			s_need_sync_fs;	atomic_t		s_active;#ifdef CONFIG_SECURITY	void                    *s_security;#endif	struct xattr_handler	**s_xattr;	struct list_head	s_inodes;	/* all inodes */	struct list_head	s_dirty;	/* dirty inodes */	struct list_head	s_io;		/* parked for writeback 等待被写回的索引节点的链表 */	struct list_head	s_more_io;	/* parked for more writeback */	struct hlist_head	s_anon;		/* anonymous dentries for (nfs) exporting */	struct list_head	s_files;        /*文件对象的链表*/	/* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */	struct list_head	s_dentry_lru;	/* unused dentry lru */	int			s_nr_dentry_unused;	/* # of dentry on lru */	struct block_device	*s_bdev;    /*指向块设备驱动程序的描述符的指针*/	struct mtd_info		*s_mtd;	struct list_head	s_instances;	struct quota_info	s_dquot;	/* Diskquota specific options */	int			s_frozen;	wait_queue_head_t	s_wait_unfrozen;	char s_id[32];				/* Informational name */	void 			*s_fs_info;	/* Filesystem private info */	fmode_t			s_mode;	/* 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 */ 	/* Granularity of c/m/atime in ns.Cannot be worse than a second */	u32		   s_time_gran; 	/* Filesystem subtype.  If non-empty the filesystem type field in /proc/mounts will be "type.subtype"*/	char *s_subtype;	/* Saved mount options for lazy filesystems using generic_show_options() */	char *s_options;	/* storage for asynchronous operations*/	struct list_head s_async_list;};

 vfsmount:对于每一个 mount 的文件系统,都由一个 vfsmount 结构来表示。

1 vfsmount结构描述的是一个独立文件系统的挂载信息,每个不同挂载点对应一个独立的vfsmount结构,属于同一文件系统的所有目录和文件隶属于同一个vfsmount,该vfsmount结构对应于该文件系统顶层目录,即挂载目录

2 比如对于mount /dev/sdb1 /media/Kingston,挂载点为/media/Kingston,对于Kingston这个目录,其产生新的vfsmount,独立于根文件系统挂载点/所在的vfsmount;
3 所有的vfsmount挂载点通过mnt_list双链表挂载于mnt_namespace->list链表中,该mnt命名空间可以通过任意进程获得
4 子vfsmount挂载点结构通过mnt_mounts挂载于父vfsmount的mnt_child链表中,并且mnt_parent直接指向父亲fs的vfsmount结构,从而形成层次结构
5 vfsmount的super_block结构->statfs函数可以获得该文件系统中空间的使用情况
6 对于挂载点/media/Kingston来讲,其 vfsmount->mnt_root->f_dentry->d_name.name = '/';而vfsmount->mnt_mountpoint->f_dentry->d_name.name = 'Kingston'。对于/media/Kingston下的所有目录和文件而言,都是这样的。
以上都是经过代码验证

 

struct vfsmount {    struct list_head mnt_hash;    struct vfsmount *mnt_parent;    /* fs we are mounted on */    struct dentry *mnt_mountpoint;    /* dentry of mountpoint */    struct dentry *mnt_root;    /* root of the mounted tree */  //指向这个文件系统的根目录    struct super_block *mnt_sb;    /* pointer to superblock */   // 指向这个文件系统的超级块对象    struct list_head mnt_mounts;    /* list of children, anchored here */    struct list_head mnt_child;    /* and going through their mnt_child */    int mnt_flags;    /* 4 bytes hole on 64bits arches */    const char *mnt_devname;    /* Name of device e.g. /dev/dsk/hda1 */    struct list_head mnt_list;    struct list_head mnt_expire;    /* link in fs-specific expiry list */    struct list_head mnt_share;    /* circular list of shared mounts */    struct list_head mnt_slave_list;/* list of slave mounts */    struct list_head mnt_slave;    /* slave list entry */    struct vfsmount *mnt_master;    /* slave is on master->mnt_slave_list */    struct mnt_namespace *mnt_ns;    /* containing namespace */    int mnt_id;            /* mount identifier */    int mnt_group_id;        /* peer group identifier */    /*     * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount     * to let these frequently modified fields in a separate cache line     * (so that reads of mnt_flags wont ping-pong on SMP machines)     */    atomic_t mnt_count;    int mnt_expiry_mark;        /* true if marked for expiry */    int mnt_pinned;    int mnt_ghosts;    /*     * This value is not stable unless all of the mnt_writers[] spinlocks     * are held, and all mnt_writer[]s on this mount have 0 as their ->count     */    atomic_t __mnt_writers;};

目录项对象

 每个文件除了有一个索引节点inode数据结构外,还有一个目录项dentry(directory enrty)数据结构。dentry 结构中有个d_inode指针指向相应的inode结构。既然inode结构和dentry结构都是对文件各方面属性的描述,那为什么不把这两个结构“合而为一”呢?这是因为二者所描述的目标不同,dentry结构代表的是逻辑意义上的文件,所描述的是文件逻辑上的属性,因此,目录项对象在磁盘上并没有对应的映像;而inode结构代表的是物理意义上的文件,记录的是物理上的属性,对于一个具体的文件系统(如Ext2),Ext2_ inode结构在磁盘上就有对应的映像。所以说,一个索引节点对象可能对应多个目录项对象

dentry 的定义在include/linux/dcache.h中:

struct dentry {    atomic_t d_count;    unsigned int d_flags;        /* protected by d_lock 目录项引用计数器*/    spinlock_t d_lock;        /* per dentry lock */    int d_mounted;    struct inode *d_inode;        /* Where the name belongs to - NULL is* negative 与文件名关联的索引节点*/    /* The next three fields are touched by __d_lookup.  Place them here so they all fit in a cache line.*/    struct hlist_node d_hash;    /* lookup hash list 目录项形成的哈希表 */    struct dentry *d_parent;    /* parent directory 父目录的目录项*/    struct qstr d_name; //目录项名(可快速查找)    struct list_head d_lru;        /* LRU list 未使用的 LRU 链表*/    /*d_child and d_rcu can share memory*/    union {        struct list_head d_child;    /* child of parent list 父目录的子目录项所形成的链表  */         struct rcu_head d_rcu;    } d_u;    struct list_head d_subdirs;    /* our children 该目录项的子目录所形成的链表*/    struct list_head d_alias;    /* inode alias list 索引节点别名的链表 */    unsigned long d_time;        /* used by d_revalidate 由 d_revalidate函数使用 */    const struct dentry_operations *d_op;/*目录项的函数集*/    struct super_block *d_sb;    /* The root of the dentry tree 目录项树的根 (即文件的超级块) */    void *d_fsdata;            /* fs-specific data具体文件系统的数据 */    unsigned char d_iname[DNAME_INLINE_LEN_MIN];    /* small names 短文件名*/};

一个有效的dentry结构必定有一个inode结构,这是因为一个目录项要么代表着一个文件,要么代表着一个目录,而目录实际上也是文件。所以,只要dentry结构是有效的,则其指针d_inode必定指向一个inode结构。可是,反过来则不然,一个inode却可能对应着不止一个dentry结构;也就是说,一个文件可以有不止一个文件名或路径名。这是因为一个已经建立的文件可以被连接(link)到其他文件名。所以在inode结构中有一个队列i_dentry,凡是代表着同一个文件的所有目录项都通过其dentry结构中的d_alias域挂入相应inode结构中的i_dentry队列。

在内核中有一个哈希表dentry_hashtable ,是一个list_head的指针数组。一旦在内存中建立起一个目录节点的dentry 结构,该dentry结构就通过其d_hash域链入哈希表中的某个队列中。内核中还有一个队列dentry_unused,凡是已经没有用户(count域为0)使用的dentry结构就通过其d_lru域挂入这个队列。

Dentry结构中除了d_alias 、d_hash、d_lru三个队列外,还有d_vfsmnt、d_child及d_subdir三个队列。其中d_vfsmnt仅在该dentry为一个安装点时才使用。另外,当该目录节点有父目录时,则其dentry结构就通过d_child挂入其父节点的d_subdirs队列中,同时又通过指针d_parent指向其父目录的dentry结构,而它自己各个子目录的dentry结构则挂在其d_subdirs域指向的队列中。

对于一个文件(linux下的都是文件),判断文件是不是目录,或者是不是链接是通过inode;

如果是目录,inode->i_op->lookup方法,一定不为空;

如果是链接,inode->i_op->fllow_link方法,一定不为空;

从上面的叙述可以看出,一个文件系统中所有目录项结构或组织为一个哈希表,或组织为一颗树,或按照某种需要组织为一个链表,这将为文件访问和文件路径搜索奠定下良好的基础。

 

 

转载于:https://www.cnblogs.com/linengier/archive/2013/04/01/2993455.html

你可能感兴趣的文章
AwSnap:让全版本(Windows、iOS、Android)Chrome浏览器崩溃的有趣漏洞
查看>>
线段树合并学习笔记
查看>>
AndroidAutoLayout
查看>>
样本不均衡下的分类损失函数
查看>>
node启动服务后,窗口不能关闭。pm2了解一下
查看>>
vsCode 改变主题
查看>>
【vijos】【树形dp】佳佳的魔法药水
查看>>
聚合新闻头条
查看>>
Ubuntu 关闭锁屏界面的 on-screen keyboard
查看>>
凸优化学习笔记
查看>>
使用ehcache-spring-annotations开启ehcache的注解功能
查看>>
Charles设置HTTPS抓包
查看>>
NGUI出现Shader wants normals, but the mesh UIAtlas doesn't have them
查看>>
Boost.Asio c++ 网络编程翻译(14)
查看>>
Codeforces Round #306 (Div. 2) D.E. 解题报告
查看>>
uva 1557 - Calendar Game(博弈)
查看>>
HDU1051 Wooden Sticks 【贪婪】
查看>>
十大经典数据挖掘算法
查看>>
Rhythmbox乱码的解决的方法
查看>>
中纪委:抗震中官员临危退缩玩忽职守将被严处
查看>>