前面把目录项、 inode、dentry、fd、硬链接这些概念理顺之后,再往下看文件系统时,很快就会碰到另一组特别容易混在一起的词:
- 文件 I/O
- 阻塞 / 非阻塞
- 同步 / 异步
- 缓冲 I/O
- 直接 I/O
- page cache
fsync
这些概念之所以容易乱,不是因为它们都难,而是因为它们其实不在同一个层面上。
有的在描述:
- 怎么打开和读写文件
前面把目录项、 inode、dentry、fd、硬链接这些概念理顺之后,再往下看文件系统时,很快就会碰到另一组特别容易混在一起的词:
fsync这些概念之所以容易乱,不是因为它们都难,而是因为它们其实不在同一个层面上。
有的在描述:
前面把文件 I/O、page cache、直接 I/O 这些内容顺了一遍之后,再往下看网络传输和文件发送时,我发现还有一块特别容易听懂关键词、但一串起来就开始乱的内容:
mmapsendfile一开始我对“零拷贝”这个词的直觉是:是不是数据完全不拷贝了,直接从磁盘飞到网卡?后来越看越发现,不是这么回事。
更准确地说:
前面把目录项、inode、dentry、fd 这些对象关系先理顺之后,再回头看文件系统,接下来最自然的问题其实是两件事:
前者更偏“文件的存储方式”,后者更偏“空闲空间管理”。这两块问题经常会放在一起讲,但本质上其实是在回答两个不同的问题:
文件存储解决的是“这个文件的数据块怎么组织、怎么找到”,空闲空间管理解决的是“还有哪些块可以继续分配”。
所以这一篇我想把这两条线先拆开,再放回到同一张图里看。
前面在整理进程、线程、同步这些内容时,我更多是在关注执行流和资源竞争。真正开始看文件系统之后,我发现这部分最容易让人混乱的地方,不是概念本身有多难,而是很多概念都长得很像:
如果不把这些层次拆开,就很容易越学越乱。所以这篇先不急着展开 ext4、日志恢复这些更底层的话题,而是先把文件系统里最基础的一条主线理顺:
一个路径到底是怎么被解析的,一个文件到底由哪些结构共同表示,磁盘上的结构和内存里的结构又分别是什么。
前面把目录项、inode、dentry、fd、page cache 这条主线先理了一遍之后,我发现文件系统里还有一组概念特别容易混在一起:
它们看起来都是在“改文件”,但实际上很多时候改的并不是文件内容,而是名字和目录项这一层的关系。把这部分看清之后,很多现象就会顺起来,比如: