linux内核如何根据文件名索引到文件内容

https://zhuanlan.zhihu.com/p/78724124

根据文件名索引到文件内容

表面上,用户通过文件名,打开文件。实际上,系统内部这个过程分成三步:首先,系统找到这个文件名对应的inode号码;其次,通过inode号码,获取inode信息;最后,根据inode信息,找到文件数据所在的block,读出数据。

现在举一个具体的例子,来说明文件是怎么读取到的,比如读取/home/bzw/test里的内容,目录结构如下图


假设文件系统的的简单分区如下

获取home对应的inode号:先找根目录'/'的inode(不考虑缓存):根目录的inode号可以从super_block中获取,ext4文件系统的根目录inode号为2(xfs文件系统根目录inode号是64,ceph文件系统根目录inode号是1),所以在索引区读取inode号为2存的inode内容。假如inode中存的block地址是1000,那么去数据区读取地址为1000的block存的内容,内容如下图所示。

地址为1000的block存的内容

地址为1000的block里面存了20个目录项(struct ext4_dir_entry),可以找到目录home对应的inode号为100。

获取bzw对应的inode号:上一步获取到了目录home的inode号,在索引区读取inode号为100存的inode内容。假如inode中存的block地址为2000,那么去读地址为2000的block存的内容,内容如下图所示。

地址为2000的block存的内容

地址为2000的block里面存了3个目录项(struct ext4_dir_entry),可以找到目录bzw对应的inode号为200。

获取test对应的inode号:上一步获取到了目录bzw的inode号,在索引区读取inode号为200存的inode内容。假如inode中存的block地址为3000,那么去读地址为3000的block存的内容,内容如下图所示。

地址为3000的block存的内容

地址为3000的block里面存了2个目录项(struct ext4_dir_entry),可以找到文件test对应的inode号为300。

获取test对应的内容:上一步获取到了文件test的inode号,在索引区读取inode号为300存的inode内容。假如inode中存的block地址为4000,那么去读地址为4000的block存的内容。这个时候就完成了操作。

这里注意如果test内容很大,那么在inode里面存的block地址就不止一个了。

可以以ext4中的struct ext4_inode为例

struct ext4_inode {

__le16 i_mode; /* File mode /
__le16 i_uid; /
Low 16 bits of Owner Uid /
__le32 i_size_lo; /
Size in bytes /
__le32 i_atime; /
Access time /
__le32 i_ctime; /
Inode Change time /
__le32 i_mtime; /
Modification time /
__le32 i_dtime; /
Deletion Time /
__le16 i_gid; /
Low 16 bits of Group Id /
__le16 i_links_count; /
Links count /
__le32 i_blocks_lo; /
Blocks count /
__le32 i_flags; /
File flags /
...
__le32 i_block[EXT4_N_BLOCKS];/
Pointers to blocks / 这里面存的就是block的地址
__le32 i_generation; /
File version (for NFS) /
__le32 i_file_acl_lo; /
File ACL /
__le32 i_size_high;
__le32 i_obso_faddr; /
Obsoleted fragment address /
...
__le16 i_extra_isize;
__le16 i_checksum_hi; /
crc32c(uuid+inum+inode) BE /
__le32 i_ctime_extra; /
extra Change time (nsec << 2 | epoch) /
__le32 i_mtime_extra; /
extra Modification time(nsec << 2 | epoch) /
__le32 i_atime_extra; /
extra Access time (nsec << 2 | epoch) /
__le32 i_crtime; /
File Creation time /
__le32 i_crtime_extra; /
extra FileCreationtime (nsec << 2 | epoch) /
__le32 i_version_hi; /
high 32 bits for 64-bit version /
__le32 i_projid; /
Project ID */

};

EXT4_N_BLOCKS定义如下,即为15,其中EXT4_IND_BLOCK为12,表示有12个直接索引表,然后有1个一级间接索引表,1个二级间接索引表,1个三级间接索引表。

/*

  • Constants relative to the data blocks
    */
    #define EXT4_NDIR_BLOCKS 12
    #define EXT4_IND_BLOCK EXT4_NDIR_BLOCKS
    #define EXT4_DIND_BLOCK (EXT4_IND_BLOCK + 1)
    #define EXT4_TIND_BLOCK (EXT4_DIND_BLOCK + 1)
    #define EXT4_N_BLOCKS (EXT4_TIND_BLOCK + 1)
    inode_hashtable

那么根目录inode号为2是怎么获取到的?

我们可以知道,在mount文件系统时,会在内存中建立一个super_block;而在struct super_block中有struct dentry *s_root成员,s_root就指向的是根目录的dentry,而在struct dentry中有struct inode *d_inode成员,保存的是根目录的inode,inode号就可以从inode中获取。不需要再去读索引区中inode为2的inode内容,因为这部分内容已经在缓存中了,只需要去根目录具体所指的block区读取目录项即可。

相关推荐
CYRUS_STUDIO15 小时前
用 Frida 控制 Android 线程:kill 命令、挂起与恢复全解析
android·linux·逆向
熊猫李17 小时前
rootfs-根文件系统详解
linux
dessler19 小时前
Hadoop HDFS-高可用集群部署
linux·运维·hdfs
泽泽爱旅行19 小时前
awk 语法解析-前端学习
linux·前端
轻松Ai享生活2 天前
5 节课深入学习Linux Cgroups
linux
christine-rr2 天前
linux常用命令(4)——压缩命令
linux·服务器·redis
三坛海会大神5552 天前
LVS与Keepalived详解(二)LVS负载均衡实现实操
linux·负载均衡·lvs
東雪蓮☆2 天前
深入理解 LVS-DR 模式与 Keepalived 高可用集群
linux·运维·服务器·lvs
乌萨奇也要立志学C++2 天前
【Linux】进程概念(二):进程查看与 fork 初探
linux·运维·服务器
獭.獭.2 天前
Linux -- 信号【上】
linux·运维·服务器