linux文件系统学习笔记 ----- dentry inode 文件的读写过程代码分析

  1. 复习dentry相关内容文件目录是一个树形的结构,为了保存这个树形结构 ,需要有一个合理的数据结构。这个数据结构就是dentry,dentry是一个纯粹的内存结构,由文件系统在提供文件访问的过程中在内存中直接建立
    linux文件系统学习笔记 ----- dentry inode 文件的读写过程代码分析
    其中对于文件夹 d_subdirs 存放了其子文件,与给定目录下的所 有文件和子目录相关联的dentry实例,都归入到d_subdirs链表(在目录对应的dentry实例中)。子 结点的d_child成员充当链表元素。内存中所有活动的dentry实例都保存在一个散列表中,该散列表使用fs/dcache.c中的全局变量 dentry_hashtable实现。用d_hash实现的溢出链,用于解决散列碰撞。因为dentry缓存只包含文件系统结构的一小部分。最 常用文件和目录对应的目录项才保存在内存中。原则上,可以为所有文件系统对象都生成dentry项, 但物理内存空间和性能原因都限制了这样做。Dentry是一个线程层面上的概念 ,一个文件可以有多个dentry,dentry还保存了文件与进程之间通信所需的信息。线程在访问文件时,会生成dentry

(1) Linux系统内核为文件设置了一个缓存,所有文件的读写的数据内容均缓存在这里,称之为page cache 。使用page cahe的IO称之为 bugger IO,内核默认使用buffer IO,由应用自身提供内存,则称之为direct IO, 所有的异步IO均为direct IO
(2) 为了方便读取缓存中的数据,引入了buffer head 这种数据结构,其不存放实际的数据,只是用来标识文件块的序号,以及文件块的缓存的地址。
(3) 为了管理page_cache 引入了address_space 数据结构 ,运用了运用了一种数据结构 好像是红黑树 保存文件内容的缓存页。 内容实在太过复杂。。。

文件读过程代码分析:文件读的入口为 sys_read 函数 ,在内核代码中 使用宏进行了替换:
linux文件系统学习笔记 ----- dentry inode 文件的读写过程代码分析
首先 使用文件ID fd 获取file对象的指针,所有打开了的文件都会保存在内存中,(每一个进程都有一个保存了当前进程中打开文件的file_struct结构体。) File_pos_read 获取当前文件读到哪了。然后调用vfs_read()函数。 在我阅读的内核代码中 vfs_read() 函数是__vfs_read()的封装
linux文件系统学习笔记 ----- dentry inode 文件的读写过程代码分析
经过一系列安全判断后,执行__vfs_read()函数
linux文件系统学习笔记 ----- dentry inode 文件的读写过程代码分析
__vfs_read()函数会先尝试调用文件系统中自定义的read()函数,如果read()函数不存在,则尝试调用read_iter() 4.15.0内核版本中自带的文件系统大多只实现了read_iter()观察ext2中read_iter的实现
linux文件系统学习笔记 ----- dentry inode 文件的读写过程代码分析
其中 iov_iter 是一个iov结构体的迭代器之后分generic_fire_read_iter()就涉及底层区块操作了,看不懂,估计我目前也用不上。

文件读调用过程跟文件写基本一致。

碎碎念:使用 attribute ((packed)) ,让编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,这样子两边都需要使用 attribute ((packed))取消优化对齐,就不会出现对齐的错位现象。