xv6 file system
在我看来文件系统某种程度上是最复杂的一部分(单从页数也足以说明了),而且我对文件系统的了解其实很少,因此这部分仔细看了一下。
xv6文件系统提供类似unix的文件、目录和路径名,并将其数据存储在virtio磁盘上以实现持久化。
文件系统解决了几个挑战:
- 文件系统需要磁盘上的数据结构来表示目录树和文件,记录保存每个文件内容的块的标识,并记录磁盘的哪些区域是空闲的。
- 文件系统必须支持崩溃恢复。也就是说,如果发生崩溃,文件系统必须在重新启动后仍能正常工作。
- 不同的进程可能同时在文件系统上操作,因此文件系统代码必须协调以维护invariants(这个词一直不知道怎么翻译,应该是修改过程需要原子操作的量,修改前后具有相同含义,但过程中可能变化)。
- 访问磁盘比访问内存慢几个数量级,因此文件系统必须在内存中维护缓存。
xv6文件系统一共有七层。
disk
磁盘硬件传统上将磁盘上的数据表示为512字节块,即扇区。操作系统为其文件系统使用的块大小可能与磁盘使用的扇区大小不同,但块大小通常是扇区大小的倍数。Xv6在buf中保存已读入内存的块的副本。存储在这个结构中的数据有时与磁盘不同步:它可能还没有从磁盘读入(磁盘正在处理它,但还没有返回扇区的内容),或者它可能已经被软件更新了,但还没有写入磁盘。
xv6将磁盘划分为几个部分,文件系统不使用块0(它包含引导扇区)。区块1是超级区块(由一个名为mkfs的单独程序填充,构建一个初始文件系统),它包含有关文件系统的元数据(以块为单位的文件系统大小、数据块数量、inode数量和日志中的块数量)。从2开始的块记录日志,之后是inodes,之后是位图块,记录数据块使用情况,剩下的块是数据块。
buffer
Buffer cache有两个任务
- 同步对磁盘块的访问,以确保内存中只有一个块的副本,并且一次只有一个内核线程使用该副本;
- 缓存常用块,提供快速读写。
buffer的主接口由bread和bwrite组成,前者获取一个包含可在内存中读取或修改的块副本,后者将修改后的缓冲区写入磁盘上相应的块,二者均调用virtio_disk_rw。bget获取LRU缓冲队列对应块号的缓存,或者未缓存时选取队尾缓存,无论哪种情况返回的缓存块都带锁(每个缓存块各自的睡眠锁,而不是缓存整体的那把大自旋锁),保证一次只有一个线程使用该缓存块。brelse释放缓存块的睡眠锁。bio.c中双链和各种操作的实现非常规整,简单易读,值得学习。
buf缓冲区有两个与之相关联的状态字段。字段valid表示缓冲区包含该块的副本。字段disk表示缓冲区内容已被交给磁盘。
xv6并未实现缓存的置换,在没有空闲块时,只是简单地panic。为什么不选择队尾的块置换呢?或者睡眠?也许是简单吧QAQ
logger
这部分描述得好抽象啊,看书完全不懂,结合代码看了好久
标签:log,ip,system,xv6,file,磁盘,inode,节点,struct From: https://www.cnblogs.com/wangerblog/p/17875689.html