文件管理
文件管理
初识文件管理
文件的定义:一组有意义的信息的集合
文件的属性
- 文件名:同一目录下不允许有同名文件
- 标识符:一个系统内的各文件标识符唯一。
- 类型
- 位置:文件存放的路径。
- 大小
- 创建时间
- 上次修改时间
- 文件所有者信息
- 保护信息:对文件进行保护的访问控制信息。
文件内部数据应该怎样组织起来
文件的逻辑结构
- 无结构文件:有一系列二进制或者字符流组成
- 有结构文件:各个记录如何组织? 是文件的逻辑结构 要重点探讨的问题。
文件之间应该怎样组织起来?
目录结构
系统中的各个文件就通过一层一层的目录合理有序的组织起来了。
文件系统应该向上提供哪些功能
-
创建文件:create系统调用
-
删除文件:delete系统调用
-
读文件:read系统调用
-
写文件:write系统调用
-
打开文件:open系统调用
-
关闭文件:close系统调用
可以使用几个基本操作完成更复杂的操作。
从上往下看,文件应如何存放外存?
- 文件应该如何存放在外存中: 文件的物理结构
- 操作系统如何管理外存中的空闲块 : 存储空间的管理
其他需要由操作系统实现的文件管理功能
- 文件共享:使多个用户可以共享使用一个文件
- 文件保护:如何保证不同的用户对文件有不同的操作权限
文件系统管理目标
设计文件系统需要考虑的主要问题
- 时间:文件访问速度快。
- 空间:文件占用内存。
- 效率:磁盘空间效率高。
什么是文件和文件系统?为什么引进文件系统
文件是有名字的记录在外存中的一组有逻辑意义的数据项的序列
文件系统是OS中用来管理文件的那一部分软件
-
长期保存(大量的)数据
-
方便用户使用(包括共享)
文件系统的作用?
文件系统的功能:
- 统一管理文件的存储空间,实施存储空间的分配与回收
- 实现文件信息的共享,提供文件的保护和保密措施
- 实现文件的按名访问
- 访问的透明性:用户不关心文件的物理位置和存储结构
- 向用户提供一个方便使用的接口,提供对文件系统操作的命令
- 提供与I/O的统一接口
用户观点
文件系统如何呈现在用户面前:一个文件由什么组成,如何命名,如何保护文件,可以进行何种操作等等
尽可能方便用户使用
系统观点
文件目录怎样实现,怎样管理文件存储空间,文件存储位置,与设备管理的接口,等等.
尽可能提高效率(时间,空间)
文件的逻辑结构
重点了解每种结构的特点和适用性
计算和过程要会(读盘次数)。
逻辑结构:在用户看来,文件内部的数据应该使如何组织起来的。
物理结构:在操作系统看来,文件的数据是如何存放在外存中的。
无结构文件
文件内部数据就是一系列的二进制流或字符流组成。又称“流式文件”。eg:.txt文件
Unix的所有文件都看作字节流文件
好处:非常灵活
有结构文件
顺序文件
串结构
记录之间的顺序与关键字无关
顺序结构
记录之间的顺序按关键字顺序排列
其中可变长记录的顺序结构也可以叫做链式结构。(如同链表)
特点:定长记录、顺序结构的顺序文件可以快速检索(根据关键字快速找到记录
可变长记录的顶序文件无法实现随机存取,定长记录可以
缺点:不方便增加/删除记录
索引文件
对于可变长记录文件,要找到第ⅰ个记录,必须先顺序第查找前i-1个记录,但是很多应用场景中又必须使用可变长记录。如何解决这个问题?
索引表本身就是定长记录的顺序文件一个索引表项就是一条定长记录,因此索引文件可支持随机存取
若索引表按关键字顷序排列,则可支持快速检索。
优点:解决了顺序文件不方便增删记录的问题,同时让不定长记录的文件实现了随机存取。但索引表可能占用很多空间
索引顺序文件
文件目录
查目录是文件系统最频繁的操作,因此目录的合理组织很重要
文件控制块(FCB)
目录本身就是一种有结构文件,由一条条记录组成。每条记录对应一个在该放在该目录下的文件。
目录文件中的一条记录就是一个“文件控制块FCB”
FCB的有序集合称为“文件目录”,一个FCB就是一个文件目录项。
FCB中包含了文件的基本信息(文件名、物理地址、逻辑结构、物理结构等),存取控制信息(是否可读可写、禁止访问的用户名单等),使用信息(如文件的建立时间、修改时间等)。
对目录项的操作:
- 搜索:当用户要使用一个文件时,系统要根据文件名搜索目录,找到该文件对应的目录项
- 创建文件:创建一个新文件时,需要在其所属的目录中增加一个目录项
- 删除文件:当删除一个文件时,需要在目录中删除相应的目录项
- 显示目录:用户可以请求显示目录的内容,如显示该目录中的所有文件及相应属性
- 修改目录:某些文件属性保存在目录中,因此这些属性变化时需要修改相应的目录项(如:文件重命名)
目录结构
单级目录结构
早期操作系统并不支持多级目录,整个系统中只建立一张目录表,每个文件占一个目录项。
- 单级目录实现了“按名存取”,但是不允许文件重名。
- 在创建一个文件时,需要先检查目录表中有没有重名文件,确定不重名后才能允许建立文件,并将新文件对应的目录项插入目录表中。
- 显然,单级目录结构不适用于多用户操作系统。
- 顺序检索文件时,平均检索时间长
两级目录结构
早期的多用户操作系统,采用两级目录结构。分为主文件目录(MFD,Master File Directory)和用户文件目录(UFD,User Flie Directory.)。
目录分为两级: 一级称为主文件目录,给出用户名,用户子目录所在的物理位置; 二级称为用户文件目录(又称用户子目录),给出该用户所有文件的FCB
优点:一定程度上解决了文件的重名和文件共享问题
查找时间缩短
缺点:增加了系统开销
多级目录结构
又称树形目录结构
用户(或用户进程)要访问某个文件时要用文件路径名标识文件,文件路径名是个字符串。各级目录之间用“/”隔开。从根目录出发的路径称为绝对路径。
例如:自拍.jpg的绝对路径是“/照片/2015-08/自拍jpg”
优点:树形目录结构可以很方便地对文件进行分类,层次结构清晰,也能够更有效地进行文件的管理和保护。
缺点:但是,树形结构不便于实现文件的共享。为此,提出了“无环图目录结构”。
无环图目录结构
在树形目录结构的基础上,增加一些指向同一节点的有向边,使整个目录成为一个有向无环图。可以更方便地实现多个用户间的文件共享。
可以用不同的文件名指向同一个文件,甚至可以指向同一个目录(共享同一目录下的所有内容)。
需要为每个共享结点设置一个共享计数器,用于记录此时有多少个地方在共享该结点。用户提出删除结点的请求时,只是删除该用户的FCB、并使共享计数器减1,并不会直接删除共享结点。
文件目录检索
访问文件时,必须首先确定读写文件的地址,需要下列2步:
(1)目录检索:根据文件名,查目录,确定文件的起始地址。
(2)文件寻址:确定所要访问文件内容的起始位置(地址)。
目录检索
文件的“按名存取”是通过查目录实现的,系统按照文件的路径名检索基本的目录检索技术主要有:
- 线性检索法
- Hash方法
为了加快目录检索,许多系统引入当前目录(工作目录)、相对路径名等.
文件寻址
根据目录项(FCB)中记录的文件物理地址等信息,
求出文件的任意记录或字节在存取介质上的地址
文件寻址与文件的物理结构和逻辑结构以及设备的物理特性有关文件的内容是以块为单位存储的。
但存取文件时,对于记录式文件,是以逻辑记录为单位提出存取要求的,因此,存储介质上的物理块长度与逻辑记录的长度是否匹配直接影响到对文件的寻址。
文件的物理结构
连续分配
连续分配方式要求每个文件在磁盘上占有一组连续的块。
目录项:起始块号和文件长度。
优点:
- 支持顺序访问和直接访问。
- 连续分配的文件在顺序读/写时速度最快。
缺点:
- 物理上采用连续分配的文件拓展不方便。
- 不利于文件内容的插入和删除。
- 存储空间利用率低,会产生难以利用的磁盘碎片。可以用紧凑来处理碎片,但是需要耗费很大的时间代价。
链接分配(链式结构)
链接分配采用离散分配的方式,可以为文件分配离散的磁盘块。分为隐式链接和显式链接。
隐式链接
目录中记录了文件存放的起始块号和结束块号。当然,也可以增加一个字段来表示文件的长度。
除了文件的最后一个磁盘块之外,每个磁盘块中都会保存指向下一个盘块的指针,这些指针对用户是透明的。
用户给出要访问的逻辑块i,操作系统找到该文件对应的目录项(FCB)。
从目录项中找到起始块号(0号块),将0号逻辑块号读入内存,由此可知道1号逻辑块存放的物理块号,于是读入1号逻辑块,再找到2号逻辑块的存放位置…以此类推。因此,读入号逻辑块,总共需要i+1次磁盘I/O。
优点:
- 方便文件拓展,不会有碎片问题,外存利用率高。
缺点:
- 采用链式分配(隐式链接)方式的文件,只支持顺序访问,不支持随机访问,查找效率低。另外,指向下一个盘块的指针也需要耗费少量的存储空间。
显式链接
题目中说链接分配,默认是隐式链接分配方式。
目录中只需记录文件的起始块号
把用于链接文件各物理块的指针显式地存放在一张表中。即 文件分配表(FAT,File Allocation Table)
注意:一个磁盘仅设置一张FAT。开机时,将FAT读入内存,并常驻内存。FAT的各个表项在物理上连续存储,且每一个表项长度相同,因此“物理块号”字段可以是隐含的。
如何实现逻辑快好到物理块号的转变?
用户给出要访问的逻辑块号ⅰ,操作系统找到该文件对应的目录项(FCB)
从目录项中找到起始块号,若i>0,则查询内存中的文件分配表FAT,往后找到ⅰ号逻辑块对应的物理块号。逻辑块号转换成物理块号的过程不需要读磁盘操作。
优点:
- 很方便文件拓展,不会有碎片问题,外存利用率高,并且支持随机访问。相比于隐式链接来说,地址转换时不需要访问磁盘,因此文件访问效率更高。
缺点:
- 文件分配表需要占用一定的内存空间。
链式结构的变形:文件分配表FAT(File Allocation Table)
一般以簇为单位分配空间,簇由若干连续的物理块组成
文件分配表FAT的一种实现:磁盘的每个分区包含一个FAT,分区中的每个盘块在其中占有1项(以块号为索引),指出文件中下一块的块号。在目录项中包含文件首块的块号。
索引分配
索引分配允许文件离散地分配在各个磁盘块中,系统会为每个文件建立一张索引表,索引表中记录了文件的各个逻辑块对应的物理块(索引表的功能类似于内存管理中的页表一一建立逻辑页面到物理页之间的映射关系)。索引表存放的磁盘块称为索引块。文件数据存放的磁盘块称为数据块。
目录中需要记录文件的索引块是几号磁盘块
用户给出要访问的逻辑块号ⅰ,操作系统找到该文件对应的目录项(FCB)
从目录项中可知索引表存放位置,将索引表从外存读入内存,并查找索引表即可只ⅰ号逻辑块在外存中的存放位置。
优点:
- 索引分配方式可以支持随机访问,文件拓展也很容易实现。(只需要给文件分配一个空闲块,并增加一个索引表项即可)
缺点:
- 需要占用一部分存储空间。
如何解决索引表太大,一个索引装不下
链接方案
如果索引表太大,一个索引块装不下,那么可以将多个索引块链接起来存放。
缺陷:若想要访问文件的最后一个逻辑块,就必须找到最后一个索引块(第256个索引块),而各个索引块之间是用指针链接起来的,因此必须先顺序地读入前255个索引块。
查找效率低下。
多层索引
建立多层索引(原理类似于多级页表)。使第一层索引块指向第二层的索引块。还可根据文件大小的要求再建立第三层、第四层索引块。
假设磁盘块大小为1KB,一个索引表项占4B,则一个磁盘块只能存放256个索引项。
若某文件采用两层索引,则该文件的最大长度可以到
256×256×1KB=65536KB=64MB可根据逻辑块号算出应该查找索引表中的哪个表项。
如:要访问1026号逻辑块,则
1026/256=4,1026%256=2因此可以先将一级索引表调入内存,查询4号表项,将其对应的二级索引表调入内存,再查询二级索引表的2号表项即可知道1026号逻辑块存放的磁盘块号了。
访问目标数据块,需要3次磁盘I/O。
- 采用K层索引结构,且顶级索引表未调入内存,则访问一个数据块只需要K+1次读磁盘操作
缺点:
- 即使是小文件,访问一个数据块依然需要K+1次读磁盘。
注意:文件的最大长度要会算 访问目标数据块需要几次磁盘I/O。
混合索引
混合索引:多种索引分配方式的结合。例如,一个文件的顶级索引表中,既包含直接地址索引(直接指向数据块),又包含一级间接索引(指向单层索引表)、还包含两级间接索引(指向两层索引表)。
要会根据顶级索引表计算支持的最大文件长度
优点:
- 对于小文件,只需要较少的读磁盘次数就可以访问目标数据块。(一般计算机中小文件较多)
UNIX文件系统采用的是多级混合索引结构。
总结(超重要必会)
超级超级超级重要考点:
- 要会根据多层索引、混合索引的结构计算出文件的最大长度(key:各级索
引表最大不能超过一个块);- 要能自己分析访问某个数据块所需要的读磁盘次数(Key:FCB中会存有指向顶级索引块的指针,因此可以根据FCB读入顶级索引块。每次读入下一级的索引块都需要一次读磁盘操作。另外,要注意题目条件一一顶级索引块是否已调入内存)
逻辑结构VS物理结构
通过一些具体的例子,将逻辑结构和物理结构分清楚。
eg:使用C创建无结构文件
FILE*fp=fopen("test.txt","w"); //打开文件
if(fp =NULL){
printf("打开文件失败!");
exit(0);
}
//写入1w个Hello world
for(int i=0;i<10000;i++)
fputs("Hello world!",fp);
fclose(fp); //关闭文件
要找到第16个字符 逻辑结构从用户看,整个文件占用一片连续的逻辑地址空间
FILE*fp=open ("test.txt","r");、/以"读"方式打开文件
if(fp =NULL){
puts("Fail to open file!");
exit(0);
}
fseek(fp,16,SEEK_SET);//读写指针指向16
char c = fgetc(fp);//从读写指针所指位置读出1个字符
printf("字符:%c",c);//打印从文件读出的字符
fclose(fp);//关闭文件
物理结构,从操作系统看,拆分成若干块,逻辑块号相邻
顺序文件
从用户的角度来看:
使用C语言实现
写就是使用数组来实现。 读就是使用一次访问就行。
也可以使用链式存储的方式。 也就是链表存储。
从操作系统的角度来看(物理结构)
索引文件
索引文件的索引表:用户自己建立的。映射:关键字->记录存放的逻辑地址
索引分配的索引表:操作系统建立的,映射:逻辑块号->物理块号
文件的使用
为什么要open/close文件?
open:把文件说明信息(FCB)装入内存,便于以后的快速访问。(1)根据指定的文件路径名,查目录,找到相应文件的目录项,检查权限;(2)将文件说明信息装入内存;(3)分配一个文件id(整数)。后面通过该id实施对该文件的操作。
close: (1)释放文件说明信息所占的内存空间; (2)把文件缓冲区中已修改的内容写回文件。 很多系统限制进程打开文件的个数,用户尽可能要关闭不再使用的文件。
创建文件
操作系统在处理Create系统调用时,主要做了两件事:
- 在外存中找到文件所需的空间(结合上小节学习的空闲链表法、位示图、成组链接法等管理策略,找到空闲空间)
- 根据文件存放路径的信息找到该目录对应的目录文件(此处就是D:/Demo目录),在目录中创建该文件对应的目录项。目录项中包含了文件名、文件在外存中的存放位置等信息。
删除文件
操作系统在处理Delete系统调用时,主要做了几件事:
- 根据文件存放路径找到相应的目录文件,从目录中找到文件名对应的目录项
- 根据该目录项记录的文件在外存的存放位置、文件大小等信息,回收文件占用的磁盘块。(回收磁盘块时,根据空闲表法、空闲链表法、位图法等管理策略的不同,需要做不同的处理)
- 从目录表中删除文件对应的目录项。
打开文件
操作系统在处理open系统调用时,主要做了几件事:
- 根据文件存放路径找到相应的目录文件,从目录中找到文件名对应的的目录项,并检查该用户是否有指定的操作权限。
- 将目录项复制 到内存中的“打开文件表”中。并将对应表目的编号返回给用户。之后用户使用打开文件表的编号来指明要操作的文件。
关闭文件
进程使用完文件后,要“关闭文件”
操作系统在处理Close系统调用时,主要做了几件事:
- 将进程的打开文件表相应表项删除
- 回收分配给该文件的内存空间等资源
- 系统打开文件表的打开计数器count减1,若count=0,则删除对应表项。
读文件
进程使用read系统调用完成写操作。需要指明是哪个文件(在支持“打开文件”操作的系统中,只需要提供文件在打开文件表中的索引号即可),还需要指明要读入多少数据(如:读入1KB)、指明读入的数据要放在内存中的什么位置。
操作系统在处理read系统调用时,会从读指针指向的外存中,将用户指定大小的数据读入用户指定的内存区域中。
写文件
进程使用wite系统调用完成写操作,需要指明是哪个文件(在支持“打开文件”操作的系统中,只需要提供文件在打开文件表中的索引号即可),还需要指明要写出多少数据(如:写出1KB)、写回外存的数据放在内存中的什么位置。
文件共享
注意:多个用户共享同一个文件,意味着系统中只有“一份”文件数据。并且只要某个用户修改了该文件的数据,其他用户也可以看到文件数据的变化。
如果是多个用户都“复制”了同一个文件,那么系统中会有“好几份”文件数据。其中一个用户修改了自己的那份文件数据,对其他用户的文件数据并没有影响。
基于索引结点的共享方式(硬链接)
知识回顾:索引结点,是一种文件目录瘦身策略。由于检索文件时只需用到文件名,因此可以将除了文件名之外的其他信息放到索引结点中。这样目录项就只需要包含文件名、索引结点指针。
索引结点中设置一个链接计数变量cout,用于表示链接到本索引结点上的用户目录项数。若count=2,说明此时有两个用户目录项链接到该索引结点上,或者说是有两个用户在共享此文件。
若某个用户决定“删除”该文件、则只是要把用户目录中与该文件对应的目录项删除,且索引结点的count值减1。
若cout>0,说明还有别的用户要使用该文件,暂时不能把文件数据删除,否则会导致指针悬空。当count=0时系统负责删除文件。
基于符号链的共享方式(软链接)
当User3访问“ccc”时,操作系统判断文件“ccc”属于Link类型文件,于是会根据其中记录的路径层层查找目录,最终找到User1的目录表中的“aaa”表项,于是就找到了文件1的索引结点。
类似于我们的快捷方式。
文件存取控制
未完待续。。。。。。
文件存储空间管理
本文来自彬彬zhidao的博客,作者:彬彬zhidao,转载请注明原文链接:https://www.cnblogs.com/binbinzhidao/p/17852250.html