dentry与inode

首先看dentry数据结构。位于include/linux/dcache.h中 struct dentry

ps:dentry虽然是目录的意思,但是在vfs中,目录和文件都有自己的dentry。(dentry中存了文件名,同一文件存在别名就是这个结构实现的)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

struct dentry {

atomic_td_count;目录项对象使用计数器

unsignedintd_flags;目录项标志

structinode*d_inode;与文件名关联的索引节点

structdentry*d_parent;父目录的目录项对象

structlist_headd_hash;散列表表项的指针

structlist_headd_lru;未使用链表的指针

structlist_headd_child;父目录中目录项对象的链表的指针

structlist_headd_subdirs;对目录而言,表示子目录目录项对象的链表

structlist_headd_alias;相关索引节点(别名)的链表

intd_mounted;对于安装点而言,表示被安装文件系统根项

structqstrd_name;文件名

unsignedlongd_time;/*usedbyd_revalidate*/

structdentry_operations*d_op;目录项方法

structsuper_block*d_sb;文件的超级块对象

vunsignedlongd_vfs_flags;

void*d_fsdata;与文件系统相关的数据

unsignedchard_iname[DNAME_INLINE_LEN];存放短文件名

};

再看inode数据结构。include/linux/fs.h

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

struct inode {/*vfs中数据结构 数据结构中各项的含义见 Linux 内核 465页*/

    struct hlist_node   i_hash;

    struct list_head    i_list;     /* backing dev IO list */

    struct list_head    i_sb_list;

    struct list_head    i_dentry; /*引用该索引节点的目录项对象链表表头*/

    unsigned long       i_ino;/*索引节点号*/

    atomic_t        i_count;

    unsigned int        i_nlink;

    uid_t           i_uid;

    gid_t           i_gid;

    dev_t           i_rdev;

    unsigned int        i_blkbits;

    u64         i_version;

    loff_t          i_size;

#ifdef __NEED_I_SIZE_ORDERED

    seqcount_t      i_size_seqcount;

#endif

    struct timespec     i_atime;

    struct timespec     i_mtime;

    struct timespec     i_ctime;

    blkcnt_t        i_blocks;

    unsigned short          i_bytes;

    umode_t         i_mode;

    spinlock_t      i_lock; /* i_blocks, i_bytes, maybe i_size */

    struct mutex        i_mutex;

    struct rw_semaphore i_alloc_sem;

    const struct inode_operations   *i_op;/*与索引结点有关的操作*/

    const struct file_operations    *i_fop; /* former ->i_op->default_file_ops */

    struct super_block  *i_sb;

    struct file_lock    *i_flock;

    struct address_space    *i_mapping;

    struct address_space    i_data;

#ifdef CONFIG_QUOTA

    struct dquot        *i_dquot[MAXQUOTAS];

#endif

    struct list_head    i_devices;

    union {

        struct pipe_inode_info  *i_pipe;

        struct block_device *i_bdev;

        struct cdev     *i_cdev;

    };

    __u32           i_generation;

#ifdef CONFIG_FSNOTIFY

    __u32           i_fsnotify_mask; /* all events this inode cares about */

    struct hlist_head   i_fsnotify_mark_entries; /* fsnotify mark entries */

#endif

#ifdef CONFIG_INOTIFY

    struct list_head    inotify_watches; /* watches on this inode */

    struct mutex        inotify_mutex;  /* protects the watches list */

#endif

    unsigned long       i_state;

    unsigned long       dirtied_when;   /* jiffies of first dirtying */

    unsigned int        i_flags;

    atomic_t        i_writecount;

#ifdef CONFIG_SECURITY

    void            *i_security;

#endif

#ifdef CONFIG_FS_POSIX_ACL

    struct posix_acl    *i_acl;

    struct posix_acl    *i_default_acl;

#endif

    void            *i_private; /* fs or device private pointer */

}

"文件"即按一定形式存储在介质上的信息,该信息包含两方面,其一是存储的数据本身,其二是文件的元信息以及记录数据占用的block的id的索引数据(这些信息都组织在文件对应的inode中)。在内存中,每个文件都有一个inode和dentry结构。dentry记录文件名,上级目录,子目录等信息,正是我们看到的(目录树、文件树)树状结构;inode记录着文件在存储介质上的位置和分布,dentry->d_inode指向对应的inode结构。inode代表物理意义上的文件,通过inode可以得到一个数组,这个数组记录文件内容的位置,若数组为(4,5,9),则对应数据位于硬盘的4,5,9块(这里只是一种简化表示,实际上记录文件内容所在的block的id,并不是一个简单的数据搞定的)。其索引节点号(就是inode号)为inode->ino,根据ino就可以计算出对应硬盘中inode的具体位置。


dentry所描述的是逻辑意义上的文件,所描述的是文件逻辑上的属性,所以dentry在磁盘上没有对应的映像;而inode结构代表的是物理意义上的文件,故磁盘上也有inode结构。

inode结构中有一个队列i_dentry,凡是代表同一个文件的所有目录项都通过d_alias域挂入相应的inode结构中的i_dentry队列。或者说,由于硬链接的存在,同一个文件可能有多种表示形式,可以成为别名,但它们都对应同一个文件,也就对应同一个inode,所以inode中有一个字段来将这些别名串起来,采用的是链表的形式。


进程打开一个文件,就会有一个file结构与之对应,同一个进程可以多次打开同一个文件而得到多个不同的file结构,file结构描述了被打开文件的属性,读写偏移指针等

两个不同的file可以对应同一个dentry结构,进程多次打开一个文件,对应只有一个dentry结构,dentry存的是目录项和对应文件的inode的信息。

在介质中,每个文件对应一个inode结点,每个文件可有多个文件名,即可以通过不同的文件名访问同一个文件,多个文件名对应一个文件的关系就是数据结构中dentry和inode多对一的关系。inode中不存储文件名字,只有节点号,通过节点号(ino),可以找到数据在介质中的具体位置,即通过内存inode结构中的ino可以定位到磁盘上的inode结构;而dentry则保存文件名和对应的节点号(inode号),这样就可以实现不同文件名访问一个inode。不同的dentry是通过ln指令实现的。


dentry树描绘了文件系统目录结构,但整个目录结构不能长驻内存,因为非常大。内存装不下。

初始状态下,系统只有代表根目录的dentry和所指向的inode(在根文件系统中挂载生成)。此时要打开一个文件,文件路径对应的结点不存在,根目录的dentry无法找到需要的子节点。这时需要通过inode->i_op中lookup方法找到inode的子节点,找到后,再创建一个dentry与之关联。

由这个过程可以看出。先有inode,再有dentry。

当生成的dentry无人使用时被释放,d_count字段记录了dentry的引用计数,引用为0时,dentry被释放。这里的释放不是直接销毁,而是将dentry放入一个“最近最少使用”队列。当队列过大,内存紧缺时,dentry才被释放。这个LRU队列就像是一个缓存池, 加速了对重复的路径的访问. 而当dentry被真正释放时, 它所对应的inode将被减引用. 如果引用为0, inode也被释放.

故需找一个文件路径时,有三种情况:

1.dentry引用大于0,直接在dentry树中找

2.dentry不在树种,在lru队列中找,LRU队列中的dentry被散列到一个散列表中,便于查找,若找到,则重新添加到dentry树中。

3.若2也未找到,则去找inode,找到后,再创建对应的dentry

这里补充每个目录项对象可以出于以下四种状态之一:

1:空闲状态  即该目录项不包含有效的信息,且没被VFS使用。

2.未使用状态  该对象的d_count计数为0,但d_inode指向关联的索引节点(inode)

3.正在使用状态  该对象的d_count计数不为0,但d_inode指向关联的索引节点

4.负状态   与目录项关联的索引节点不存在了


mount过程:

linux首先找到磁盘分区的super block,然后通过解析磁盘的inode table与file data。构建出自己的dentry列表和inode列表。VFS是按照Ext的方法进行构建的,两者非常相似。如inode结点。ext_inode结点中的一些成员变量其实是没有用的,如引用计数等,保留目的是为了和vfs-inode保持一致,这样在用ext_inode构建vfs_inode时,就不需要一个个赋值,只需要一次拷贝。

故非ext格式的文件系统,mount的过程会慢一些


根目录有一个dentry结构,而根目录里的文件和目录都链接到这个根dentry;同样的道理,二级目录里的文件和目录链接到二级目录,这样一层层,就形成了一颗dentry树。从树顶可以遍历整个文件系统。

为了加快对dentry的查找,内核使用hash表来缓存dentry,称为dentry cache,dentry一般现在dentry cache中查找(与之对应的,inode也会在内核空间使用hash表进行缓存,文件的内容,则采用页高速缓存page cache来缓存,而使用address_space和基树进行管理page cache中的页)。

dentry结构里有d_subdirs成员和d_child成员。d_subdirs是子项的链表头,所有的子项都要链接在这个链表上,d_child是自身链表头,需要连接到父dentry的d_subdirs成员。

d_parent是指针,指向父dentry结构。

d_hash是连接到dentry cache的hash链表。

d_name保存目录或文件的名字。打开一个文件的时候,根据这个成员和用户输入的名字来搜寻目标。

d_mounted用来指示dentry是否是一个挂载点。如果是,则成员不为零。


dentry的hash定位,通过d_hash()函数将父目录dentry的地址和所要查找的文件名的hash值结合起来,重新计算一个hash值,并根据其定位到dentry_hashtable哈希表中(即定位某个表头,缩小查找范围),该表是dentry缓存一部分,接下来扫描该链表,从中找到目标dentry,若没有找到,则通过real_lookup()函数从磁盘中查找。


目录项对象存放在dentry_cache的slab高速缓存中。故目录项的创建和删除是通过kmem_cache_alloc()和kmem_cache_free()实现的。目录项高速缓存由两种类型数据结构组成:

1.处于正在使用、未使用或负状态的目录项对象的集合。

2.一个散列表。用于hash快速查找给定文件名和目录名对应的目录项对象。散列表是由dentry_hashtable数组实现。数组中每个元素是一个指向链表的指针。

dentry与inode相关推荐

  1. Linux那些事儿之我是Sysfs(7)dentry与inode

    我们在进程中要怎样去描述一个文件呢?我们用目录项(dentry)和索引节点(inode).它们的定义如下: include/linux/dcache.h struct dentry { /* RCU ...

  2. 【文件】VFS四大struct:file、dentry、inode、super_block 是什么?区别?关系?--编辑中...

    简略 推荐:<VFS.超级块.inode.dentry.file>https://www.itdaan.com/blog/2014/08/31/f99ae6e6e574449076a385 ...

  3. dentry和inode的关系

    vfs 是具体文件系统(如 ext4.nfs.fat)和 Kernel 之间的桥梁,它将各个文件系统抽象出来并提供一个统一的机制来组织和管理各个文件系统,但具体的实现策略则由各个文件系统来实现,这很好 ...

  4. dentry 和inode

    转载:https://blog.csdn.net/qq_34501940/article/details/51192257 dentry dentry是一个内存实体,其中的d_inode成员指向对应的 ...

  5. 【操作系统】LinuxKernel-VFS虚拟文件系统 认知框架构建(super_block,inode,dentry,file)

    VFS 概念 虚拟文件系统(也称为虚拟文件系统交换机)是内核中的软件层,为用户空间程序提供文件系统接口.它还在内核中提供了一个抽象,允许不同的文件系统实现共存 "一切皆文件"是Li ...

  6. Linux 虚拟文件系统四大对象:超级块、inode、dentry、file之间关系

    一:文件系统 1. 什么是文件系统? 操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统. 通常文件系统是用于存储和组织文件的一种机制,便于对文件进行方便的查找与访问. 文件系统 ...

  7. linux文件系统dentry_文件系统中超级块、inode和dentry三者的分析

    原标题:文件系统中超级块.inode和dentry三者的分析 文件系统是用于存储和组织文件的一种机制,便于对文件进行方便的查找与访问. 而随着文件种类的增多,扩增了更多的文件系统,为了对各种文件系统进 ...

  8. linux 内核 目录项高速缓存 dentry cache 简介

    每个dentry对象都属于下列几种状态之一: (1)未使用(unused)状态:该dentry对象的引用计数d_count的值为0,但其d_inode指针仍然指向相关的的索引节点.该目录项仍然包含有效 ...

  9. kernel部分数据结构列表三(inode)

    kernel部分数据结构列表三(inode) /* *索引节点对象由inode结构体表示,定义文件在linux/fs.h中 */ struct inode {         struct hlist ...

最新文章

  1. javascript高级程序设计之变量、作用域和内存问题
  2. Java并发编程的艺术(一)——并发编程需要注意的问题
  3. step1 . day7 C语言基础练习之指针和函数
  4. 销售流程图_34页财务管理制度和流程图!让你明白会计工作要点,总结全面清晰...
  5. 洛谷 P2051 [AHOI2009]中国象棋 状态压缩思想DP
  6. django配置文件
  7. 浅谈声纹识别应用:声音被模仿,声音识别身份可靠吗?
  8. python数学公式编辑工具_也许是目前最好的数学公式编辑神器——Mathpix Snipping Tool...
  9. 【单片机】2.1 AT89S52单片机的硬件组成
  10. CSS三大特性(层叠/继承/优先)
  11. javaweb区分PC端和移动端
  12. .NET 中各种混淆(Obfuscation)的含义、原理、实际效果和不同级别的差异(使用 SmartAssembly)
  13. ISO26262道路车辆功能安全标准-(1)适用范围
  14. 服务器80端口找不到,如何查询服务器80端口被关闭
  15. 职通未来 The Next One——赴一场不一样的招聘会
  16. SWD模式下无法识别到芯片
  17. 数字图像处理,图像的伪彩色处理
  18. VC下载文件 + 显示进度条
  19. 乐鑫esp8266学习rtos3.0笔记第4篇:带你捋一捋微信公众号 airkiss 配网 esp8266 并绑定设备的过程,移植并成功实现在 esp8266 rtos3.1 sdk。(附带demo)
  20. 我近4年的计算机学习经历

热门文章

  1. 【开发】前端工程——ReactJS
  2. 你为你的机会准备了什么
  3. 异地多活(异地双活)实践经验
  4. DM8更换产品授权,更换KEY
  5. 如何合并同一个磁盘里面的两个区(卷)
  6. CWnd和HWND的区别
  7. 视频播放器(二)——播放列表
  8. 安装gfortran
  9. 单片机作业1_为OLED制作汉字字库_第3部分
  10. 移动端超高品质的Axure UI设计/交互设计组件库,几乎涵盖了所有的组件