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区读取目录项即可。

相关推荐
什么半岛铁盒19 分钟前
【Linux系统】Linux环境变量:系统配置的隐形指挥官
linux
Lw老王要学习1 小时前
Linux容器篇、第一章_02Rocky9.5 系统下 Docker 的持久化操作与 Dockerfile 指令详解
linux·运维·docker·容器·云计算
橙子小哥的代码世界1 小时前
【大模型RAG】Docker 一键部署 Milvus 完整攻略
linux·docker·大模型·milvus·向量数据库·rag
倔强的石头1062 小时前
【Linux指南】用户与系统基础操作
linux·运维·服务器
云上艺旅2 小时前
centos升级内核
linux·运维·centos
kaikaile19952 小时前
centos开启samba服务
linux·运维·centos
云上艺旅2 小时前
centos部署k8s v1.33版本
linux·云原生·kubernetes·centos
好多知识都想学2 小时前
Centos 7 服务器部署多网站
linux·服务器·centos
好多知识都想学2 小时前
centos 7 部署awstats 网站访问检测
linux·运维·centos
Li-Yongjun3 小时前
深度解析 Linux 内核参数 net.ipv4.tcp_rmem:优化网络性能的关键
linux·网络·tcp/ip