文件的逻辑结构、目录
文件的逻辑结构
所谓的“逻辑结构”,就是指在用户看来,文件内部的数据是如何组织起来的。而“物理结构”就是在操作系统看来,文件的数据是如何存放在外存中的
1.无结构文件
- 由一些二进制或字符流组成,又称“流式文件”。如Windows中的 .txt文件
2. 有结构文件
- 由一组相似的记录组成,又称“记录式文件”。
- 每条记录由若干数据项组成。如数据库表文件,一般来说每条记录有一个数据项可作为关键字(作为识别不同记录的ID)
- 分类:
- 定长记录
- 可变长记录
- 定长记录
1. 顺序文件
- 文件中的记录一个接一个地顺序排列(逻辑上),记录可以是定长的或可变长的
- 各个记录在物理上可以顺序存储或链式存储
- 记录排列是否按关键字排序:
- 串结构:记录之间的顺序于关键字无关
- 顺序结构:记录之间的顺序按关键字顺序排列
- ⭐数据的存取:已经知道了文件的起始地址(第一个记录存放的位置)
- 链式存储
无论是定长/可变长记录,都无法实现随机存取,每次只能从第一个记录开始依次往后找 - 顺序存储
- 可变长记录
每个记录长度不一,无法实现随机存取,每次只能从第一个记录开始依次往后找 - 定长记录
可以实现随机存取。记录长度为L,则第 i 个记录存放的相对位置为 i * L
采用串结构无法找到某关键字对应的记录
采用顺序结构,可以快速找到某关键字对应的记录(如:折半查找)
- 可变长记录
- ⭐结论:定长记录的顺序文件,如果物理上采用顺序存储,则可实现随机存取;若还能再保证记录的顺序结构,则可以实现快速检索。(即根据关键字快速找到对应记录)
- 链式存储
2. 索引文件
上面讲到对于可变长记录不能实现随机存取,但实际应用中有需要可变长记录的随机存取,如何解决?
- 建立一张索引表以加快文件检索的速度,每条记录对应一个索引表项
- ⭐索引表本身是定长记录的顺序文件。因此可以快速找到第 i 个记录对应的索引项
- ⭐每个变长记录用一个个索引表项代替,可变长记录变为了定长记录
- ⭐若索引表按关键字顺序排序,则可支持快速检索
- 适用于对信息处理的及时性要求比较高的情形
- 另外,可以用不同的数据项建立多个索引表:可以通过姓名、学号个建立一个索引表,这样使用姓名和学号就都能快速地检索文件了
3. 索引顺序文件(结合)
索引文件的缺点:每个索引表项对应一个记录,如果一个文件有很多记录,那么意味着有很多索引表项,索引表的大小就会很大
- 索引顺序文件中,并不会为每个记录建立一个索引项,而是将记录分组,为每个分组建立一个索引项(一组记录对应一个索引表项)
- 检索效率分析:
- 若一个顺序文件有10000个记录组成,若根据关键字检索文件,只能从头开始查找,平均需要查找5000个记录
- 若采用索引顺序结构文件,可以把10000个记录分成√ 10000 = 100 组,根据分组建立索引表,每组对应一个索引表项,这样要查找一个记录时,只需要 ① 先查找索引表找到记录所在的分组,② 再去这个分组内找到想要的记录,故需要平均查找 50 + 50 = 100个记录
4. 多级索引顺序文件
如过索引顺序文件有 106 个记录,若按1000 个记录为一组,算下来需要平均查找 500 + 500 = 1000个记录,还是很多,怎么办?
- 为了进一步提高查找效率,可以为顺序文件建立多级索引表
- 例如上例中, 有 106 个记录,按100个记录为一组,共10000组,建立次级索引表,再将10000个分组再分组成100个组,建立顶级索引表,
- 这样算下来平均查找 50 + 50 + 50 = 150 个记录
文件的目录
1. 文件控制块
实现文件目录的关键数据结构
- 目录本身就是一种有结构文件,由一条条记录组成。每条记录对应一个放在该目录下的文件
- 一个目录有一个目录文件
- 目录文件中的一条记录就是一个“文件控制块”(FCB)
- FCB的有序集合称为“文件目录”,一个FCB就是一个文件目录项
- FCB中包含了文件的基本信息(文件名、物理地址、逻辑地址、物理结构等),存取控制信息(是否可读/可写、禁止访问的用户名单),使用信息(文件建立、修改时间)
- 最重要的还是 文件名 、文件存放的物理地址
- FCB实现了文件名和文件之间的映射,使用户(用户程序)可以实现“按名存取”
- 需要对目录进行哪些操作?
- 搜索:当用户要使用一个文件时,系统要根据文件名搜索目录,找到该文件对应的目录项
- 创建文件:创建一个文件时,需要在其所属的目录中增加一个目录项
- 删除文件:当删除一个文件时,需要在目录中删除相应的目录项
- 显示目录:用户可以请求显示目录的内容,如显示该目录中的所有文件及相应属性
- 修改目录:某些文件属性保护在目录中,因此这些属性变化时需要修改相应的目录项(如文件重命名)
2. 目录结构
单级目录结构
- 单级目录实现了“按名存取”,但是不允许文件重名
- 在创建一个文件时,需要先检查目录表中有没有重名文件,确定不重名后才能允许建立文件,并将新文件对应的目录项插入目录表中
- 缺点:单级目录结构不适合多用户操作
两级目录结构
- 分为主文件目录和用户文件目录
- 主文件目录:记录用户名及相应用户文件目录的存放位置
- 用户文件目录:由该用户的文件FCB组成
- 两级目录结构允许不同用户的文件重名,也可以在目录上实现访问限制(检查此时登陆的用户名是否匹配)
- 缺点:但是两级目录结构仍然缺乏灵活性,用户不能对自己的文件进行分类(每个用户只有一个目录表)
- 允许不同用户的文件重名。文件名虽然相同,但是对应的其实是不同的文件
多级目录结构(树形)
- 用户要访问某个文件时要用文件路径名标识文件,文件路径名是个字符串。各级目录间用 / 隔开
- 绝对路径:从根目录出发的路径
- 系统根据绝对路径一层层找到下一级目录,
① 刚开始从外存读入根目录的目录表;
② 找到“照片”目录的存放位置后,从外存读入相应的目录表;
③ 再找到“2015-08”目录存放的位置,在从外存读入对应的目录表;
最后找到文件“自拍.jpg”的存放位置,整个过程需要3次读取磁盘I/O操作 - 很多时候,用户会连续访问同一个目录内的多个文件,显然每次都从根目录开始很不方便
- 系统根据绝对路径一层层找到下一级目录,
- 相对路径:
- 每次从根目录开始很不方便,所有可以使用从当前目录出发的“相对路径”
- 例如:此时已经打开了“照片”目录表,也就是说这张目录表已经调入内存,那么可以把它设置成“当前目录”。当用户想要访问某个文件时,所有可以使用从当前目录出发的“相对路径”
- 优点:树形目录结构可以很方便地对文件进行分类,层次结构清晰,也能够有效地进行文件管理和保护
- 缺点:树形结构不方便实现文件的共享
无环图目录结构
- 在树形目录结构的基础上,增加一些指向同一结点的有向边,是整个目录成为一个有向无环图,方便文件共享
- 可以用不同的文件名指向同一个文件,甚至可以指向同一个目录(共享目录下的所有内容)
- 需要为每个结点设置一个共享计数器,用于记录目前由多少地方共享该节点
- 用户提出删除结点的请求时,只是删除该用户下文件对应的FCB,并使计数器减一,并不会直接删除结点
- 只有共享计数器减为0时,才删除该节点
- 共享文件不同于文件的复制:在共享文件中,由于各用户指向同一个文件,因此只要其中一个用户修改了文件数据,那么所有用户都可以看到文件内容的变化
3. 索引结点(FCB的改进)
- 其实在查找各级目录的过程中只需要用到“文件名”这个信息,只有文件名匹配时,才需要读出文件的其他信息。因此,可以考虑让目录表瘦身来提升效率
- 改进目的: 减小FCB的大小,使得一个磁盘块能存放更多的FCB,从而减少磁盘块数→减少磁盘I/O
- 改造:
- 有何好处:
- 假设一个FCB(目录项)是64B,磁盘块大小为1KB,则每个磁盘块中能放1KB/64B=16个FCB。若一个文件目录中共有640个目录项,则需要640/16=40个磁盘块。故平均需要启动磁盘20次(每次I/O磁盘读入一块)
- 使用索引节结后,假设一个文件名占14B,索引结点指针占2B,一个目录项是16B,磁盘块大小为1KB,则每个磁盘块中能放1KB/16B=64个FCB。若一个文件目录中共有640个目录项,则需要640/64=10个磁盘块。故平均需要启动磁盘5次(每次I/O磁盘读入一块)
- 当找到文件名对应的目录项时,才需要将索引结点调入内存,索引结点中记录了文件的各种信息,包括文件在外存中存放位置,根据“存放位置”即可找到文件
- 存放在外存中的索引结点称为“磁盘索引结点”,当索引结点放入内存后称为“内存索引结点”——相比之下,内存索引结点需要增加几个信息,如:文件是否被修改、此时有几个进程正在访问该文件你