L12:文件系统

lab通关记录

MIT-6.828实验通关记录

课程总览

文件系统
磁盘
磁盘布局
xv6 案例研究

问题开胃

为什么文件系统有用?
重启的持久性:为了系统崩溃后恢复时数据的稳定
命名和组织:方便
在程序和用户之间共享:我们通过pathname找到文件,而不是块或者页,符合人的习惯

为什么有趣?
崩溃恢复
表现
分享
安全
抽象很有用:管道、设备、/proc、/afs、Plan 9
所以面向 FS 的应用程序可以处理多种对象
你将为 JOS 实现一个

API 示例——UNIX/Posix/Linux/xv6/&c:

1
2
3
4
fd = open("x/y", -);
write(fd,“ABC”,3);
link(“x/y”,“x/z”);
unlink(“x/y”);

UNIX FS API 中可见的高级选项
对象:文件(与虚拟磁盘、DB)
内容:字节数组(对比 80 字节记录,BTree)
命名:人类可读(与对象 ID)
组织:名称层次结构
同步:无(与锁定,版本)
还有其他文件系统 API,有时完全不同!

API 的一些含义:
fd 指的是file descriptor:句柄(可以理解为一种多级指针)
即使文件名更改也会保留
或者如果文件在打开时被删除!
一个文件可以有多个链接(pathname)
即出现在多个目录中
这些事件中没有一个是特别的
所以文件必须有信息存储在目录以外的地方:info node
因此:
FS 在磁盘上的“inode”中记录文件信息
FS 指的是带有 i-number 的 inode(FD 的内部版本)
inode 必须有链接数(告诉我们何时释放)
inode 必须有打开的 FD 数
inode 解除分配推迟到最后一个链接和 FD 消失

让我们谈谈 xv6

FS 软件层
系统调用
名称操作 | FD 操作
节点
节点缓存
日志
缓冲区缓存
驱动程序

xv6的文件系统磁盘布局

IDE 是与设备对话的标准
https://en.wikipedia.org/wiki/Parallel_ATA

1
2
3
4
5
6
7
8
9
简介:
先进技术附件(英语:Advanced Technology Attachment,简称“ATA”)是用于连接存储设备的接口标准,与由集成驱动电子设备(英语:Integrated Drive Electronics,简称IDE)技术实现的磁盘驱动器关系最密切。

IDE是一种计算机系统接口,主要用于硬盘和CD-ROM,本意为“把控制器与盘体集成在一起的硬盘”。数年以前PC主机使用的硬盘,大多数都是IDE兼容的,只需用一根电缆将它们与主板或接口卡连起来就可以了,而目前主要接口为SATA接口。而在SATA技术日益发展下,支持ATA的主板已不再出现,而且Intel在新型的芯片组中已经不默认支持ATA接口,主机版厂商需要另加芯片去对ATA作出支持(通常是为了兼容旧有硬盘和光盘驱动器)。

SATA(Serial ATA)于2002年推出后,原有的ATA改名为PATA(并行高技术配置,Parallel ATA)。[1] 2013年12月29日,西部数据正式停止PATA硬盘供应,而希捷科技则已停售产多年,这意味着1986年设计的PATA接口在经历27年后正式退出历史舞台[2][3]。

一般说来,ATA是一个控制器技术,而IDE是一个匹配它的磁盘驱动器技术,但是两个术语经常可以互用。ATA是一个花费低而性能适中的接口,主要是针对台式机而设计的,销售的大多数ATA控制器和IDE磁盘都是更高版本的,称为ATA - 2和ATA - 3,与之匹配的磁盘驱动器称为增强的IDE。

连接器、接口、协议等。
CPU 与 IDE 控制器对话
控制器与硬盘、SSD、CD-ROM 通信

硬盘驱动器 (HDD)
同心轨道
每个磁道是一个扇区序列,通常为 512 字节(柱面->磁道->扇区)
磁头必须寻道,磁盘必须旋转
随机访问很慢(每次访问 5 或 10 毫秒)
顺序访问要快得多(100 MB/秒)
每个扇区的 ECC
只能读/写整个扇区
因此:子扇区写入代价高昂(读-修改-写)

固态硬盘 (SSD)
非易失性“闪存”存储器
随机访问:100 微秒
顺序:500 MB/秒
内部复杂——隐藏除了有时性能
在重新写入之前必须擦除闪存
限制可写入闪存块的次数
SSD 应对一定程度的间接性——重新映射的块

对于 HDD 和 SSD:
顺序访问比随机访问快得多
大读/写比小读/写快
这些都会影响 FS 设计和性能

磁盘块
大多数 o/s 使用多个扇区的块,例如 4 KB 块 = 8 个扇区
减少簿记和寻求管理费用
为简单起见,xv6 使用单扇区块

磁盘布局
第二个 IDE 驱动器上的 xv6 文件系统;首先只有内核
xv6 将 IDE 驱动器视为扇区数组,忽略磁道结构

0:未使用(boot sector)
1:超级块(大小,ninodes)
2:日志头
32:inode 数组,打包成块
58:块使用中的位图(0=空闲,1=使用)
59:文件/目录内容块

磁盘结束

xv6 的 mkfs 程序为空文件系统生成此布局
布局在文件系统的生命周期内是静态

“元数据”metadata
磁盘上除文件内容以外的所有内容
超级块、索引节点、位图、目录内容

磁盘索引节点

type(free、file, dir、dev)
Link cnt
size
block addr[12+1]

直接块和间接块

例子:
如何找到文件的字节 8000?
逻辑块 15 = 8000 / 512
间接块中的第三个条目

每个 i-node 都有一个 i-number
!!很容易把 i-number 变成 inode
inode 是 64 字节长
磁盘上的字节地址:32512 + 64inum

目录内容
目录当作一个文件
但用户不能直接写
内容是目录的数组

1
2
3
4
5
6
7
8
假如我有一个pathname:/home/hello/hello.c需要通过这个pathname和文件系统找到hello.c?
1.我只能访问根目录/
2./文件里找到了home
3.home文件里找到了hello
4.hello文件里找到了hello.c

以上,123步骤中都是文件,但是他们都属于目录文件,只有hello.c才是我们要的目标文件。
因此,假如我增加了这个文件hello.c,实际上向上相关的目录文件都会进行更改/增加,通过这种方式构造了一个文件树的概念

直接:
枚举
14 字节的文件名
如果 inum 为零,dirent 是免费的

您应该将 FS 视为磁盘上的数据结构
[树:目录、索引节点、块]
有两个分配池:索引节点和块

让我们看看实际运行中的 xv6
专注于磁盘写入
通过如何更新说明磁盘上的数据结构

问:xv6 如何创建文件?

1
2
3
4
5
6
7
8
9
10
11
12
$ echo > a
write 34 ialloc (from create sysfile.c; mark it non-free)
write 34 iupdate (from create; initialize nlink &c)
write 59 writei (from dirlink fs.c, from create)

call graph:
sys_open sysfile.c
create sysfile.c
ialloc fs.c
iupdate fs.c
dirlink fs.c
writei fs.c

问:第 34 块中有什么?
查看 sysfile.c 中的 create()

问:为什么 two 写入块 34?

问:59 块是什么?

Q:如果并发调用ialloc怎么办?
他们会得到相同的 inode 吗?
在 ialloc 中注意面包 / 写 / brelse
面包锁定块,可能等待,并从磁盘读取
brese 解锁方块

问:xv6 如何将数据写入文件?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ echo x > a
write 58 balloc (from bmap, from writei)
write 508 bzero
write 508 writei (from filewrite file.c)
write 34 iupdate (from writei)
write 508 writei
write 34 iupdate

call graph:
sys_write sysfile.c
filewrite file.c
writei fs.c
bmap
balloc
bzero
iupdate

问:第 58 块中有什么?
看看 writei 对 bmap 的调用
看看 bmap 对 balloc 的调用

问:508 块中有什么?

Q:为什么是iupdate?
文件长度和地址[]

问:为什么两个 writei+iupdate?
echo 调用 write() 两次,第二次调用换行符

问:xv6 如何删除文件?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ rm a
write 59 writei (from sys_unlink; directory content)
write 34 iupdate (from sys_unlink; link count of file)
write 58 bfree (from itrunc, from iput)
write 34 iupdate (from itrunc; zeroed length)
write 34 iupdate (from iput; marked free)

call graph:
sys_unlink
writei
iupdate
iunlockput
iput
itrunc
bfree
iupdate
iupdate

问:第 59 块中有什么?
sysfile.c 中的 sys_unlink

问:第 34 块中有什么?

问:第 58 块中有什么?
看输入

Q:为什么是三个iupdate?

我们来看看bio.c中的块缓存
块缓存只保存几个最近使用的块
bio.c 开始时的 bcache

FS调用bread,调用bget
bget 查看块是否已经缓存
如果存在而不是 B_BUSY,则返回块
如果存在且 B_BUSY,则等待
如果不存在,重新使用现有的缓冲区
b->refcnt++ 防止 buf 在我们等待时被回收

这里有两级锁定
bcache.lock 保护缓存中内容的描述
buf->lock 只保护一个缓冲区

Q:什么是LRU替换策略?
简单来说,就是时间轴的更新

1.如果使用,就放到队尾

2.如果替换,那么先替换队头(拿出清除后放入)

问:那是最好的更换政策吗?

Q:如果有很多进程需要读盘怎么办?谁先走?
iderw 附加到 idequeue 列表
ideintr 在 idequeue 列表的头部调用 idestart
先进先出

问:FIFO (先进先出)是一个好的磁盘调度策略吗?
优先调度?
电梯排序?

问:为什么拥有 I/O 的双重副本是有意义的?
磁盘到缓冲缓存
缓冲区缓存到用户空间
我们可以修复它以获得更好的性能吗?

问:我们应该为磁盘缓冲区分配多少 RAM?

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2020-2024 环烷烃
  • Visitors: | Views:

我很可爱,请我喝一瓶怡宝吧~

支付宝
微信