Linux文件系统(三)
目录
路径与文件名
路径解析
路径缓存
挂载分区
路径与文件名
我们访问文件通常使用的是文件名而不是inode号,所以操作系统必须能够记录下两者的映射关系,由于文件都是属于目录的,所以这个映射关系是由 目录记录的,目录的文件数据就是inode号和文件名的映射关系
实际上,你甚至可以用vim打开某个目录,里面会记录一些目录的信息
所以,要访问文件,必须要先打开文件所属目录,根据文件名获得对应的inode号,才能对文件进行访问
实际上在硬盘这一层级,没有目录的概念,目录也是文件
访问文件必须要知道当前工作目录,必须打开当前工作目录文件,查看目录的内容
路径解析
打开当前目录,查看当前目录的内容,可当前目录也是文件,访问当前目录也是只知道文件名,要访问当前目录,也得知道当前目录的inode号,所以还需要打开当前目录的上一级目录,于是,类似递归的,把所有目录全部解析,递归出口是 "/"目录
任何文件,都有路径,访问任何文件,都要从根目录开始,依次打开每一个目录,直到访问到目标文件
访问文件,必须加上路径,而根目录的inode号无需查找,系统开机后就知道
访问文件的路径由谁提供?
使用者访问文件,都是指令访问,本质是进程访问,进程有CWD环境变量,进程提供路径
路径缓存
由于访问任何文件都要从根目录开始路径解析,Linux会缓存历史路径结构
Linux中,在内核中维护树状路径结构的内核结构体叫做: struct dentry
struct dentry {atomic_t d_count;unsigned int d_flags;/* protected by d_lock */spinlock_t d_lock;/* per dentry lock */struct inode *d_inode; //目录的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 *//** 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 */struct dentry_operations *d_op;struct super_block *d_sb;/* The root of the dentry tree */void *d_fsdata;/* fs-specific data */#ifdef CONFIG_PROFILINGstruct dcookie_struct *d_cookie; /* cookie, if any */#endifint d_mounted;unsigned char d_iname[DNAME_INLINE_LEN_MIN];/* small names */
};
每个文件都有对应的dentry结构,包括普通文件,这样所有被打开的文件,就可以在内存中形成整个树形结构
整个树形节点也同时会⾪属于LRU(Least Recently Used,最近最少使⽤)结构中,进⾏节点淘汰
整个树形节点也同时会⾪属于Hash,⽅便快速查找
这个树形结构,整体构成了Linux的路径缓存结构,打开访问任何⽂件,都在先在这棵树下根据路径进⾏查找,找到就返回属性inode和内容,没找到就从磁盘加载路径,添加dentry结构,缓存新路径
挂载分区
现在还有一个问题待解决,如何能确定文件属于哪个分区?inode是不能跨分区的,也就是说不同分区可能有同一个inode号,仅凭inode号无法知道在哪个分区
分区写入文件系统,无法直接使用,需要挂载到某个目录上才能使用,那么,不同的分区的路径前缀就会不一样,就能根据路径前缀来判断位于哪个分区。