操作系统(13)-----文件管理3:https://developer.aliyun.com/article/1511186
1.文件控制块(实现文件目录的关键数据结构)
目录文件用于记录目录下存放的文件,例如,下图就是根目录(D盘)的目录文件。
目录本身就是一种有结构文件,由一条条记录组成。每条记录对应一个在该目录下的文件。
当我们双击“照片”后,操作系统会在这个目录表中找到关键字“照片”对应的目录项(也就是记录),然后从外存中将“照片”目录的信息读入内存,于是,“照片”目录中的内容就可以显示出来了。
同样,照片对应的目录文件也是由一条条记录组成,每个记录对应其中一个文件。目录文件中的一条文件记录就是一个文件控制块(FCB)
FCB的有序集合称为“文件目录”,一个FCB就是一个文件目录项。FCB 中包含了文件的基本信息(文件名、物理地址、逻辑结构、物理结构等),存取控制信息(是否可读/可写、禁止访问的用户名单等),使用信息(如文件的建立时间、修改时间等)。
最重要,最基本的还是文件名、文件存放的物理地址
因为FCB 实现了文件名和文件之间的映射。使用户(用户程序)可以实现“按名存取。
可以对目录进行哪些操作?
搜索:当用户要使用一个文件时,系统要根据文件名搜索目录,找到该文件对应的目录项
创建文件:创建一个新文件时,需要在其所属的目录中增加一个目录项
删除文件:当删除一个文件时,需要在目录中删除相应的目录项
显示目录:用户可以请求显示目录的内容,如显示该目录中的所有文件及相应属性
修改目录:某些文件属性保存在目录中,因此这些属性变化时需要修改相应的目录项(如:文件重命名)
2.目录结构
(1)单级目录结构:
早期操作系统并不支持多级目录,整个系统中只建立一张目录表,每个文件占一个目录项。
单级目录实现了“按名存取”,但是不允许文件重名,所以在创建一个文件时,需要先检查目录表中有没有重名文件,确定不重名后才能允许建立文件,并将新文件对应的目录项插入目录表中。
显然,单级目录结构不适用于多用户操作系统。
(2)两级目录结构:
早期的多用户操作系统,采用两级目录结构。分为主文件目录(MFD,MasterFileDirectory)和用户文件目录(UFD,User Flie Directory)
主文件目录记录用户名及相应用户文件目录的存放位置
用户文件目录由该用户的文件FCB组成
而不同用户的文件可以重名,即允许不同用户的文件重名。文件名虽然相同,但是对应的其实是不同的文件。
两级目录结构允许不同用户的文件重名,也可以在目录上实现实现访问限制(检查此时登录的用户名是否匹配)。例如,user1想要访问user2的用户文件目录,那么操作系统就可以检查user1和user2登录的用户名是否匹配,若匹配,则可以访问。
但是两级目录结构依然缺乏灵活性,用户不能对自己的文件进行分类。
(3)多级目录结构(树形目录结构):
每个目录下允许有更低一级的目录,也可以有普通文件,并且不同目录下的文件是可以重名的。
用户(或用户进程)要访问某个文件时要用文件路径名标识文件,文件路径名是个字符串。各级目录之间用“/”隔开。从根目录出发的路径称为绝对路径。
例如,自拍.jpg 的绝对路径是"/照片/2015-08/自拍.jpg"
系统根据绝对路径一层一层地找到下一级目录。刚开始 从外存读入根目录的目录表;找到“照片”目录的存放位置后, 从外存读入对应的目录表;再找到“2015-08”目录的存放位置,再从 外存读入对应目录表;最后才找到文件“自拍jpg”的存放位置。 整个过程需要3次读磁盘I/O操作。
很多时候,用户会连续访问同一目录内的多个文件(比如:接连査看“2015-08”目录内的多个照片文件),显然,每次都从根目录开始查找,是很低效的。因此可以设置一个“当前目录”。
例如,此时已经打开了“照片”的目录文件,也就是说,这张目录表已调入内存,那么可以把它设置为“当前目录”。当用户想要访问某个文件时,可以使用从当前目录出发的“相对路径”
在Linux中,表示当前目录,因此如果“照片”是当前目录,则"自拍.jpg"的相对路径为:“./2015-08/自拍.jpg”。从当前路径出发,只需要查询内存中的“照片”目录表,即可知道"2015-08"目录表的存放位置,从外存调入该目录,即可知道“自拍.jpg”存放的位置了,就是只需要经过一次I/O操作。
可见,引入“当前目录”和“相对路径”后,磁盘I/O的次数减少了。这就提升了访问文件的效率。
(4)无环图目录结构:
树形目录结构可以很方便地对文件进行分类,层次结构清晰,也能够更有效地进行文件的管理和保护。但是,树形结构不便于实现文件的共享。为此,提出了“无环图目录结构”。
在树形目录结构的基础上,增加一些指向同一节点的有向边,使整个目录成为一个有向无环图。可以更方便地实现多个用户间的文件共享。
可以用不同的文件名指向同一个文件,甚至可以指向同一个目录(共享同一目录下的所有内容,即共享一个目录,因为目录本身也是一个特殊的文件)。例如user1用户可以用demo文件名指向某文件,而user2也可以用Mydemo文件名指向该文件。
因为文件可能是被多个用户使用的,所以不能一个用户执行删除操作就进行删除,所以需要为每个共享结点设置一个共享计数器,用于记录此时有多少个地方在共享该结点。用户提出删除结点的请求时,只是删除该用户的FCB、并使共享计数器减1,并不会直接删除共享结点。只有共享计数器减为0时,才删除结点。
例如上图,user1想删除demo,那么只会对demo这个目录项进行删除,并且共享计数器减1,而这个文件对应的内容不会被直接删除。
注意:共享文件不同于复制文件。在共享文件中,由于各用户指向的是同一个文件,因此只要其中一个用户修改了文件数据,那么所有用户都可以看到文件数据的变化。而复制文件时,对副本进行修改,原来文件的数据不会变化。
3.索引结点(对文件控制块的优化)
文件目录是由一个个FCB的集合组成,但是在查找各级目录的过程中只需要用到“文件名”这个信息,只有文件名匹配时,才需要读出文件的其他信息。因此可以考虑让目录表“瘦身”来提升效率。
我们将除了文件名以外,其他冗余的数据放到索引结点中。每个文件都会对应唯一的索引结点,采用索引结点后,目录中只包含文件名和各个文件索引结点对应的指针的信息,由于目录项长度减小,因此每个磁盘块可以存放更多个目录项,因此检索文件时磁盘I/O的次数就少了很多,并且目录文件占用的空间也会少很多。
假设一个FCB是64B,磁盘块的大小为1KB,则每个盘块中只能存放16个FCB。若一个文件目录中共有640个目录项,则共需要占用640/16=40个盘块。因此按照某文件名检索该目录,平均需要查询320个目录项,平均需要启动磁盘20次(每次磁盘I/O读入一块)。
若使用索引结点机制,文件名占14B,索引结点指针占2B,则每个盘块可存放64个目录项,那么按文件名检索目录平均只需要读入320/64=5个磁盘块。显然,这将大大提升文件检索速度。
当找到文件名对应的目录项时,才需要将索引结点调入内存,索引结点中记录了文件的各种信息,包括文件在外存中的存放位置,根据“存放位置”即可找到文件。
存放在外存中的索引结点称为“磁盘索引结点”,当索引结点放入内存后称为“内存索引结点”相比之下内存索引结点中需要增加一些信息,比如:文件是否被修改、此时有几个进程正在访问该文件等。
九.其他需要由操作系统实现的文件管理功能
1.文件共享
操作系统为用户提供文件共享功能,可以让多个用户共享地使用同一个文件。
注:多个用户共享同一个文件,意味着系统中只有“一份”文件数据。并且只要某个用户修改了该文件的数据,其他用户也可以看到文件数据的变化。
如果是多个用户都“复制”了同一个文件,那么系统中会有“好几份”文件数据。其中一个用户修改了自己的那份文件数据,对其他用户的文件数据并没有影响。
(1)基于索引结点的共享方式(硬链接)
索引结点是一种文件目录瘦身策略。由于检索文件时只需用到文件名,因此可以将除了文件名之外的其他信息放到索引结点中。这样目录项就只需要包含文件名、索引结点指针。
索引结点中设置一个链接计数变量 count,用于表示链接到本索引结点上的用户目录项数。
若count=2,说明此时有两个用户目录项链接到该索引结点上,或者说是有两个用户在共享此文件。
若使用这种方式,删除文件需要注意一点:
若某个用户决定“删除”该文件,则只是要把用户目录中与该文件对应的目录项删除,且索引结点的count值减 1。
若count>0,说明还有别的用户要使用该文件,暂时不能把文件数据删除,否则会导致指针悬空。
当count=0时,系统负责删除文件。
(2)基于符号链的共享方式(软链接:符号链接)
如下图所示,若user3想要用软链接的方式,共享文件1,那么user3会建立一个文件,这个文件是Link 类型的文件(Link 类型的文件名可以不同),记录了文件1的存放路径“C:/User1/aaa”,层层查找目录,最终找到 User1的目录表中的“aaa”表项,于是就找到了文件1的索引结点。类似于 Windows 操作系统的“快捷方式”。
若此时user1和user2不需要使用文件1,由于此时count值变为0,那么文件1以及其对应的索引结点都会被删除。此时user3再访问link型的文件---文件2,操作系统会查找"aaa"的存放路径,尝试找到"aaa"对应文件的目录项,但是这一目录项已经被删除了,通过这一路径已经找不到文件1了。那么这一软链接也失效了。
由于软链接需要一级一级查询目录,即要查询多级目录,会有多次磁盘I/O操作,因此软链接的共享方式比硬链接慢。
2.文件保护
操作系统需要保护文件数据的安全。
(1)口令保护
为文件设置一个“口令”(如:abc112233),用户请求访问该文件时必须提供“口令”。
口令一般存放在文件对应的 FCB 或索引结点中。用户访问文件前需要先输入“口令”,操作系统会将用户提供的口令与FCB中存储的口令进行对比,如果正确,则允许该用户访问文件。
优点:保存口令的空间开销不多,验证口令的时间开销也很小(用户想访问文件,必然要查找FCB,所以口令保存在FCB或索引结点中,验证口令的时间开销小)。
缺点:正确的“口令”存放在系统内部,不够安全。
(2)加密保护
使用某个“密码”对文件进行加密,在访问文件时需要提供正确的“密码”才能对文件进行正确的解密。
例如:一个最简单的加密算法--异或加密,假设用于加密/解密的“密码”为“01001”
系统中保存的不是文件的原始数据,而是加密后的数据,所以用户想要访问这一文件的话,必须解密才行。
通过对比可以发现,如果加密密码和解密密码一致,那么解密结果和原始数据是一致的。
假设用户用错误的密码进行解密,那么解密结果和原始数据是不一样的。
优点:保密性强,不需要在系统中存储“密码”。
缺点:编码/译码,或者说加密/解密要花费一定时间。
口令保护与加密保护的区别在于:
口令保护的口令保存在系统中,由系统验证口令是否正确。如果正确,才能允许用户访问该文件。
加密保护的密码不需要保存在系统之中,密码只有用户自己知道。用一个“密码”对文件加密,用户想要访问文件时,需要提供相同的“密码"才能正确的解密。
所以加密保护的安全性比口令保护的安全性更高,但是加密/解密的开销需要耗费一定时间。
(3)访问控制
在每个文件的FCB(或索引结点)中增加一个访问控制列表(Access-Control List,ACL),该表中记录了各个用户可以对该文件执行哪些操作。各个系统可对文件进行的操作是不一样的。
某文件的访问控制列表如下所示,有的计算机可能会有很多个用户,因此访问控制列表可能会很大,可以用精简的访问列表解决这个问题。
精简的访问列表:以“组”为单位,标记各“组”用户可以对文件执行哪些操作,每个分组对文件的访问权限是不同的。如:分为系统管理员、文件主、文件主的伙伴、其他用户几个分组。
当某用户想要访问文件时,系统会检查该用户所属的分组是否有相应的访问权限。所以系统也需要管理分组的信息。
当“其他用户”想要读取文件,只需要把该用户放入“文件主的伙伴”这个分组即可。
对于口令保护和加密保护,只需要正确的口令或密码就可以使用户对文件进行所有类型的操作,但是对于访问控制,可以使用户对文件进行不同类型的操作:读/写/执行/删除等。实现灵活,可以实现复杂的文件保护功能。
注:如果对某个目录进行了访问权限的控制,那也要对目录下的所有文件进行相同的访问权限控制