文件系统是文件和管理信息资源的管理程序的集合,是操作系统中负责存取和管理信息的模块,它用统一的方式管理用户和系统信息的存储、检索、更新、共享和保护,并为用户提供一整套方便有效的文件使用和操作方法。
文件系统面向用户的功能是:文件的按名存取、文件的共享和保护、文件的操作和使用
为了实现这些功能,OS必须考虑:
- 文件目录的建立和维护 ?
- 存储空间的分配和回收 ?
- 数据的保密和保护 ?
- 监督用户存取和修改文件的权限 ?
- 实现在不同存储介质上信息的表示方式、编址方法、文件系统存储次序,以及信息检索等问题
所有I/O操作都通过读写文件实现,所有外设,包括网络、终端设备,都被看成文件;像磁盘、光盘等外存上的文件则是普通文件 。
通常,将键盘和显示器构成的设备称为终端(terminal),对应标准输入、标准输出、错误输出文件(ASCII文件)
所有物理设备抽象成逻辑上统一的“文件”使得用户程序访问物理设备与访问真正的磁盘文件完全一致。
如printf在stdout文件(即终端显示器TTY)显示信息,fprintf和fwrite主要输出到磁盘文件,它们都通过统一的write函数陷入内核,差别则由内核处理。
每一个进程的PCB结构中都有一个用户打开文件表/文件描述符表,表项的序号是文件描述符fd,此登记项内登记系统打开文件表的一个入口指针fp——指向一个用于描述打开的文件的file结构。
fd:一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过fd。程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。如果此时去打开一个新的文件,它的文件描述符会是3。不同进程的相同fd可能不是同一文件。
系统打开文件表的每个表项是一个file结构,不管同一进程还是不同进程,每打开一个文件就产生一个file结构,记录了当前打开文件的偏移量、指向文件活动inode的指针等数据。不同进程的文件描述符也可以指向同一file结构,从而指向同一inode且共享同一文件偏移量(例如fork的进程)。
file结构有文件访问计数f_count,记录了引用这个file结构的文件描述符个数,只有当引用计数为0时,内核才销毁它。因此某个进程关闭文件,不影响与之共享同一个file结构的进程;有读写位移指针f_offset、指向对应文件活动索引节点的指针f_inode
活动inode有引用计数i_count,硬链接计数i_nlink、索引节点号i_ino
用户通过两类接口与文件系统联系:
第一类是与文件有关的操作命令,例如cat、cd、cp、find、mv、 rm、mkdir、rmdir等等
第二类是提供给用户程序使用的文件类系统调用,基本文件类系统调用有:
- 创建并打开文件
fd = create("/home/home1/newfile" , 0775);
为新文件分配磁盘inode和活动inode,并把inode号和文件名newfile组成新目录项,记录到目录路径/home/home1的目录文件中
为新文件所对应inode设置初值,包括把存取权限设置为0775,连接计数i_nlink置为1
为新文件分配用户打开文件表项和系统打开文件表项,为后者设置初值(如特征位f_flags置写标志、读写标志f_offset清0),把用户打开文件表项、系统打开文件表项和活动inode链接起来
- 删除文件
unlink("/home/home1/newfile");
- 打开文件
fd = open("/home/home1/newfile" , 0775);
检索目录,要求打开的文件应该是已经创建的文件,它应登记在文件目录中否则会出错。在检索到指定文件后,将其磁盘inode复制到活动inode表中。(如果文件已被打开过,活动inode已有该inode,只要把其中的i_count加1即可)
把参数0775所给出的打开方式与活动inode中的文件访问权限比较,非法则打开失败。
为文件分配用户打开文件表项和系统打开文件表项,为后者设置初值,把用户打开文件表项、系统打开文件表项和活动inode链接起来
- 关闭文件
close(fd);
根据fd找到用户打开文件表项,再找到系统打开文件表项,释放用户打开文件表项。
把系统打开文件表项中的f_count减1,若不为0说明还有进程在共享这个这个系统打开文件表项,不用释放此表项。
把对应活动inode中的i_count减1,若不为0说明其它进程正在使用,否则把此活动inode的内容复制回磁盘inode,释放此活动inode
- 读文件
nr=read(fd , buf , count);
当读到文件末尾系统调用就返回,因此nr所指出的字符数有可能小于count要求的字符数。
- 写文件
n2 = write(fd , buf , count);
- 文件随机存取
lseek = (fd , offset , whence);
在文件初次打开时,文件偏移量f_offset清空为0,以后的文件读写操作总是根据offset的当前值来顺序读写文件。
可以通过lseek系统调用在读写文件之前改变f_offset的指向。
whence为0时,f_offset被置为offset;whence为0时,f_offset被置为当前f_offset加上offset;
不同进程共享同一文件,可以通过:
- 静态共享
静态共享是通过文件所对应的inode节点来实现链接的,并且只允许链接到文件而非目录。又称硬链接(Hard Link)
文件链接的系统调用为:
link(“/home/fil1/file.c” , “/home/fei2/file.c");
检索目录,找到/home/fil1/file.c所指文件的inode
再次检索目录,找到目录文件/home/fei2,并把已存在文件的inode号和别名构成目录项并加入
把已存在文件inode的连接计数i_nlink加1(新建目录时,自身i_nlink为2,上层目录i_nlink增加1)
文件解除链接的形式与文件删除相同,执行同一段系统调用代码,都是删去目录项且把i_nlink减1。i_link为0时才真正删除。
在多个分区文件目录树整合成的目录树内,inode号不能唯一标识文件,link系统调用不能跨文件系统。
可以使用bash命令:
[[email protected] ~]#ln /home/fil1/file.c /home/fei2/file.c
- 动态分享
同一用户若要创建两个进程协同完成任务,可以用父进程执行fork()函数创建子进程,两个进程的用户打开文件表指向系统打开文件表的同一file结构(f_count=2),从而指向同一活动inode且共享同一位移指针。
不同用户的不同进程的用户打开文件表指向系统打开文件表的不同file结构(f_count=1),从而指向同一活动inode且不共享指针。
- 文件符号链接共享
软链接,又称符号链接(Symbolic Link),是只有文件名不指向inode的链接,通过名称来引用文件。会建立一个占用inode和block的新文件,文件的数据部分仅包含它所要链接文件的路径名(相当于快捷方式)
可以使用bash命令:
[[email protected] ~]#ln -s /home/fil1/file.c /home/fei2/file.c
ls -l命令查询得到的文件详细信息:
lrwxrwxrwx. 1 root root 22 Jul 14 10:09 /sbin/init -> ../lib/systemd/systemd
开头的l代表文件类型是链接文件,1代表文件的连接数是1
文件系统性能问题:
(1)盘块高速缓存:系统在内存开辟存储区维护一组盘块高速缓存,它在逻辑上归属磁盘却不归属任何类型具体文件系统
优点:数据使用后会在盘块高速缓存留下备份,由于程序执行时的局部性原理,可以减少I/O操作
脏数据写会磁盘时可以适当排序,实现磁盘驱动调度优化
(2)数据预先读入:仅适用于文件的顺序访问。为了做好文件数据的预读工作,可以跟踪文件的访问模式:
开始时置访问模式标志位为1,表示当前在顺序访问模式;移臂后直置访问模式标志位为0,表示当前在随机访问模式,一段时间若又回到顺序访问模式则置回1。
(3)信息优化分布:对顺序存取的大量数据,通常不存在同一盘面的磁道上,而是同一柱面的不同磁道上。以减少磁臂移动次数。
(4)磁臂驱动调度
(5)内存映射文件:不使用文件类系统调用存取文件信息,而是把欲访问的文件映射到进程的虚存空间。访问虚拟地址信息相当于访问文件信息。特别适用于文件分享的场合。
文件系统可靠性问题:
(1)提高文件系统可靠性的措施:
①磁盘坏块管理
硬件方法:在磁盘一个扇区中记录坏块清单,当控制器第一次进行初始化时,读取坏块清单,当控制器第一次进行初始化时,读取坏块清单并且挑选备份块取代有缺陷的块,在坏块清单中记下这种映射,此后访问到坏块时就由对应备份块代替
软件方法:用户或文件系统额外构造一个文件,它包含全部坏块,把这些坏块在盘块自由链中清除而不分配给文件系统使用。
②备份数据
备份策略有完全备份、增量备份、更新备份
(2)文件系统一致性检查
①磁盘块一致性检查
磁盘块一致性检查需要检查磁盘块空闲计数器(其在空闲块链表出现的次数)+ 占用计数器(其在文件中出现的次数)=1
磁盘块一致性检查实用程序读出文件系统中所有文件的inode,为对应磁盘块占用计数器加1;再检查空闲块链表,为所有未使用磁盘块的空闲计数器加1。检查结束后两个计数器互相比较,如果一个为1一个为0说明是正常的。
情况1:空闲计数器=占用计数器=1,只要把空闲计数器置0并将磁盘块移除空闲块链表即可
情况2:空闲计数器=占用计数器=0,只要把空闲计数器置1并将磁盘块移除空闲块链表即可
情况3:空闲计数器=2、占用计数器=0,只要把空闲计数器置1并重建空闲块链表
情况4:空闲计数器=0、占用计数器=2,分配一个空闲磁盘块,把占用块的内容复制到里面,用它来替换其中一个文件的原磁盘块,并对占用计数器进行修改。这样修改文件内容未变但其中肯定有一个文件是不正确的。
②文件一致性检查
文件的一致性检查需要检查文件inode中的链接数i_count与其出现在文件系统中的次数是否一致
文件一致性检查实用程序查看目录系统,为每个文件的inode建立一个计数器,从根目录开始沿目录树依次向下查找,对于每个文件其inode计数器加1。检查结束后将计数器的值与inode中的i_count比较,相同说明是正常的。
情况1:i_count>目录项数,inode会无法释放,把i_count减少为正确值即可。
情况2:i_count>目录项数,在删除文件过程中inode会提前释放,把i_count减少为正确值即可。
原文地址:https://www.cnblogs.com/yangyuliufeng/p/9339088.html