在 linux 中常见的文件系统 有很多, 如下?
基于磁盘的文件系统, ext2, ext3, ext4, xfs, btrfs, jfs, ntfs?
内存文件系统, procfs, sysfs, tmpfs, squashfs, debugfs?
闪存文件系统, ubifs, jffs2, yaffs ?
文件系统这一套体系在 linux 有一层 vfs 抽象, 用户程序不用关心 底层文件系统的具体实现, 用户只用操作 open/read/write/ioctl/close 的相关 系统调用, 这一层系统调用 会操作 vfs 来处理响应的业务?
vfs 会有上面各种文件系统对应的 读写 相关服务, 进而 将操作下沉到 具体的文件系统?
我们这里看一下 ext4 文件系统?
将业务数据存储在磁盘的一个文件系统, 读写数据 最终会提交到磁盘设备?
将数据暂存在内存中物理页,?动态刷出到磁盘?
在创建该文件的时候,?ext4fs 会创建对应的?inode, 并将改?inode?添加到?父级节点
创建?inode 操作来自于,?父级目录的?i_op->create, ext4fs中对应于?ext4_create
这里主要是基于?ext4fs 的?super_block 新建?inode, 初始化?i_no, i_mapping, i_op, i_fop 什么的?
接下来是 查找 group, 分配文件节点,?这里可以看得出来?ext4 文件系统对于?文件数量的限定是一个 逻辑上的限定
接下来是初始化?inode/ext4_inode 的相关其他信息
普通文件的?i_fop 为?ext4_file_operations
另外就是创建了文件之后,?还需要将文件的相关信息?添加到文件夹中记录
这里?ext4_find_dest_de 会找到?父文件夹的数据内容中存放当前文件的地址, 如果有则找到?已有的文件的地址,?如果没有在父文件夹的数据内容末尾 记录当前新增文件的信息
这里?就是设置文件夹中 新增/更新文件元数据的地方
这里记录几个信息项?inode, rec_len, name_len, file_type, name ?
查看 /jerry 的文件夹的内容, buffered_head
0xffff88007dc08630: 29 '\035' 0 '\000' 0 '\000' 0 '\000' 36 '$' 0 '\000' 26 '\032' 1 '\001'
0xffff88007dc08638: 84 'T' 101 'e' 115 's' 116 't' 49 '1' 51 '3' 83 'S' 105 'i'
0xffff88007dc08640: 103 'g' 110 'n' 97 'a' 108 'l' 80 'P' 97 'a' 114 'r' 101 'e'
0xffff88007dc08648: 110 'n' 116 't' 65 'A' 110 'n' 100 'd' 67 'C' 104 'h' 105 'i'
0xffff88007dc08650: 108 'l' 100 'd' 0 '\000' 0 '\000' 30 '\036' 0 '\000' 0 '\000' 0 '\000'
0xffff88007dc08658: 36 '$' 0 '\000' 28 '\034' 1 '\001' 84 'T' 101 'e' 115 's' 116 't'
0xffff88007dc08660: 49 '1' 51 '3' 83 'S' 105 'i' 103 'g' 110 'n' 97 'a' 108 'l'
0xffff88007dc08668: 80 'P' 97 'a' 114 'r' 101 'e' 110 'n' 116 't' 65 'A' 110 'n'
0xffff88007dc08670: 100 'd' 67 'C' 104 'h' 105 'i' 108 'l' 100 'd' 46 '.' 99 'c'
0xffff88007dc08678: 31 '\037' 0 '\000' 0 '\000' 0 '\000' -120 '\210' 1 '\001' 5 '\005' 1 '\001'
0xffff88007dc08680: 50 '2' 46 '.' 116 't' 120 'x' 116 't' 0 '\000' 0 '\000' 0 '\000'
0xffff88007dc08688: 0 '\000' 0 '\000' 0 '\000' 0 '\000' 0 '\000' 0 '\000' 0 '\000' 0 '\000'
# 这里内存中的 0xffff88007dc08678 开始 为 /jerry 目录下面 我们新增的 2.txt 的数据条目
inode_no 为 0x00 00 00 1f
rec_len 为 0x01 88
name_len 为 0x05
file_type 为 0x01
name 为 2.txt
这个创建取决于实际的业务,?业务/内核 代码向 ext4fs 中写出具体的数据到具体的文件?
那么执行?该代码的时候 就会创建对应的文件
存储空间是来自于 pagecache, 然后 具体的数据是来自于 磁盘设备?
a_ops->write_begin 会获取?maping, pos 对应的物理页,?如果不存在?则向 pagecache 进行申请?
然后?iov_iter_copy_from_user_atomic 的实现是将?用户空间待写出的数据 写出到给定的 物理页,?然后?系统会定时将脏页刷出到磁盘
读取文件的时候?根据 mapping, index 获取磁盘文件块,?加载到?page?
这一部分的内容参见?从磁盘读取数据到内存的调试?
?copy_page_to_iter 即为读取的操作,?将物理页的数据拷贝到?buf 中
上面在?i_op->create 中创建了?inode, 但是并没有提到将?inode 注册到?dir?中或者怎么怎么样?
那么?读取文件的时候怎么关联找到这个 inode 呢??
然后?之后才是走的上面的 i_op->lookup 在父目录的内容中查找?目标文件的条目[ext4_dir_entry_2], 这里可以拿到?i_no, 然后使用?ext4_iget_normal 来获取对应的?inode?的信息, 这里也会缓存一份?dentry 的数据到?dcache
然后?在之后 读取该文件的时候,?lookup_fast 的时候去?dcache_hashtable 中查询对应的?dentry?的信息?
进而拿到?inode, 以及?inode 相关附加信息
进而是根据?inode, 以及上下文,?封装?file?对象
完?
?