• 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存的内容
    地址为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存的内容
    地址为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存的内容
    地址为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区读取目录项即可。

  • 相关阅读:
    云原生:10分钟了解一下Kubernetes架构
    基于dlib进行人脸识别demo
    Redis安全控制和解决方案(14)
    Git学习笔记10
    Halcon的 Filter (过滤)目录之add_Image算子
    基于javaweb仓库管理系统简易课程报告-软件工程
    二轮平衡小车3:PID速度环
    一起来部署项目-采购一台云服务器
    209.Flink(四):状态,按键分区,算子状态,状态后端。容错机制,检查点,保存点。状态一致性。flink与kafka整合
    2022年全网最全最细最流行的自动化测试工具有哪些?
  • 原文地址:https://blog.csdn.net/katerdaisy/article/details/132778330