这里写目录标题
- 一.文件系统的基本组成
- 索引节点
- 目录项
- 文件数据的存储
- 扇区
- 三个存储区域
- 二.虚拟文件系统
- 文件系统分类
- 进程文件表
- 读写过程
- 三.文件的存储
- 连续空间存放方式
- 缺点
- 非连续空间存放方式
- 链表方式
- 隐式链表
- 缺点
- 显示链接
- 索引数据库
- 缺陷
- 索引的方式优点:
- 多级索引
- 比较
- 对空闲空间管理
- 空闲链表法:
- 位图法
一.文件系统的基本组成
文件系统是操作系统中负责管理持久数据的子系统,说简单点,就是负责把用户的文件存到磁盘硬件中,因为即使计算机断电了,磁盘里的数据并不会丢失,所以可以持久化的保存文件。
- 文件系统的基本数据单位是文件,它的目的是对磁盘上的文件进行组织管理,那组织的方式不同,就会形成不同的文件系统。
- Linux中,一切皆是文件,普通目录,文件,块设备,管道,socket,等都是文件系统管理
- LInux会给每个文件分配两个数据结构:索引节点和目录项目
索引节点
- 也就是 inode,用来记录文件的元信息,比如 inode 编号、文件大小、访问权限、创建时间、修改时间、数据在磁盘的位置等等。
- 索引节点是文件的唯一标识,它们之间一一对应,也同样都会被存储在硬盘中,所以索引节点同样占用磁盘空间。
- 一个文件可以有多个别字。比如,硬链接的实现就是多个目录项中的索引节点指向同一个文件。
- 通常为了加快读取速度,当文件被访问时,会把索引节点加载到内存中去,
目录项
- 也就是 dentry,用来记录文件的名字、索引节点指针以及与其他目录项的层级关联关系。
- 多个目录项关联起来,就会形成目录结构,但它与索引节点不同的是,目录项是由内核维护的一个数据结构,不存放于磁盘,而是缓存在内存。
- 目录也是文件,也是用索引节点唯一标识,和普通文件不同的是,普通文件在磁盘里面保存的是文件数据,而目录文件在磁盘里面保存子目录或文件。
- 录是个文件,持久化存储在磁盘,而目录项是内核一个数据结构,缓存在内存。
- 存在目的:如果查询目录频繁从磁盘读,效率会很低,所以内核会把已经读过的目录用目录项这个数据结构缓存在内存,下次再次读到相同的目录时,只需从内存读就可以,大大提高了文件系统的效率。
文件数据的存储
扇区
磁盘读写的最小单位是扇区,扇区大小是512字节,为了增加读取速度,文件系统把8个扇区组合成一个逻辑块,4kb,提高了读写速率.
三个存储区域
- 超级块,用来存储文件系统的详细信息,比如块个数、块大小、空闲块等等,当文件系统被挂载时加载进内存。
- 索引节点区,用来存储索引节点。
- 数据块区,用来存储文件或目录数据
二.虚拟文件系统
文件系统种类众多,为了统一接口。在用户层和文件系统引入了中间层,这个中间层称为虚拟文件系统
VFS 定义了一组所有文件系统都支持的数据结构和标准接口,这样程序员不需要了解文件系统的工作原理,只需要了解 VFS 提供的统一接口即可
文件系统分类
- 磁盘的文件系统,他是直接把数据存储在磁盘中,比如Ext 2/3/4,XFS等都是这类文件系统
- 内存的文件系统,这类文件系统的数据是存储在内存空间的,比如常见的/proc和/sys,实际上是读写内核中的相关数据
- 网络的文件系统,用来访问其他主机上的文件系统。
进程文件表
- 每一个进程都有个文件表,文件表里的每一项代表「文件描述符」
- 文件指针:系统跟踪上次读写位置作为当前文件位置指针,这种指针对打开文件的某个进程来说是唯一的;
- 文件打开计数器:文件关闭时,操作系统必须重用其打开文件表条目,否则表内空间不够用。因为多个进程可能打开同一个文件,所以系统在删除打开文件条目之前,必须等待最后一个进程关闭文件,该计数器跟踪打开和关闭的数量,当该计数为 0 时,系统关闭文件,删除该条目;
- 文件磁盘位置:绝大多数文件操作都要求系统修改文件数据,该信息保存在内存中,以免每个操作都从磁盘中读取;
- 访问权限:每个进程打开文件都需要有一个访问模式(创建、只读、读写、添加等),该信息保存在进程的打开文件表中,以便操作系统能允许或拒绝之后的 I/O 请求
读写过程
- 当用户进程从文件读取 1 个字节大小的数据时,文件系统则需要获取字节所在的数据块,再返回数据块对应的用户进程所需的数据部分。
- 当用户进程把 1 个字节大小的数据写进文件时,文件系统则找到需要写入数据的数据块的位置,然后修改数据块中对应的部分,最后再把数据块写回磁盘。
- 文件系统的基本操作单位是数据块
三.文件的存储
文件的数据是要存储在硬盘上面的,数据在磁盘上的存放方式,就像程序在内存中存放的方式那样,有以下两种:
- 连续空间存放方式
- 非连续空间存放方式
连续空间存放方式
- 连续空间存放方式就是把文件存放在连续的物理空间中,这种情况文件数据紧密,读取速率高,磁盘一次寻道就可以读出整个文件。
- 使用连续存放的一个前提是:必须知道一个文件的大小,这样才能找到相应大小的空间分配给文件
- 文件头里面需要指定的起始块位置和长度,有这两个信息就可以很好的表示存放
缺点
存在大量的磁盘碎片空间,文件长度不易扩展的缺陷
非连续空间存放方式
非连续空间存放方式分为「链表方式」和「索引方式」
链表方式
链表的方式是离散的,不需要连续,于是就可以消除磁盘碎片,可以大大提高磁盘的利用率,同时可以支持文件长度动态扩展。
根据实现的方式的不同,链表可分为「隐式链表」和「显式链接」两种形式
隐式链表
文件要以「隐式链表」的方式存放的话,实现的方式是文件头要包含「第一块」和「最后一块」的位置,并且每个数据块里面留出一个指针空间,用来存放下一个数据块的位置,这样一个数据块连着一个数据块,从链头开是就可以顺着指针找到所有的数据块,所以存放的方式可以是不连续的。
缺点
在于无法直接访问数据块,只能通过指针顺序访问文件,以及数据块指针消耗了一定的存储空间。隐式链接分配的稳定性较差,系统在运行过程中由于软件或者硬件错误导致链表中的指针丢失或损坏,会导致文件数据的丢失
显示链接
- 如果取出每个磁盘块的指针,把它放在内存的一个表中,就可以解决上述隐式链表的两个不足。那么,这种实现方式是「显式链接」,它指把用于链接文件各数据块的指针,显式地存放在内存的一张链接表中,该表在整个磁盘仅设置一张,每个表项中存放链接指针,指向下一个数据块号
- 对于显式链接的工作方式,我们举个例子,文件 A 依次使用了磁盘块 4、7、2、10 和 12 ,文件 B 依次使用了磁盘块 6、3、11 和 14 。利用下图中的表,可以从第 4 块开始,顺着链走到最后,找到文件 A 的全部磁盘块。同样,从第 6 块开始,顺着链走到最后,也能够找出文件 B 的全部磁盘块。最后,这两个链都以一个不属于有效磁盘编号的特殊标记(如 -1 )结束。内存中的这样一个表格称为文件分配表(File Allocation Table,FAT)。
缺点是不适合大磁盘,磁盘太大导致表太大
索引数据库
- 索引的实现是为每个文件创建一个「索引数据块」,里面存放的是指向文件数据块的指针列表,说白了就像书的目录一样,要找哪个章节的内容,看目录查就可以
- 文件头需要包含指向「索引数据块」的指针,这样就可以通过文件头知道索引数据块的位置,再通过索引数据块里的索引信息找到对应的数据块
- 创建文件时,索引块的所有指针都设为空。当首次写入第 i 块时,先从空闲空间中取得一个块,再将其地址写到索引块的第 i 个条目
缺陷
就是存储索引带来的开销。
索引数据块如果空间不够,可以使用索引链表,
索引的方式优点:
- 文件的创建、增大、缩小很方便;
- 不会有碎片的问题;
- 支持顺序读写和随机读写;
多级索引
-
它是根据文件的大小,存放的方式会有所变化:
- 如果存放文件所需的数据块小于 10 块,则采用直接查找的方式;
- 如果存放文件所需的数据块超过 10 块,则采用一级间接索引方式;
- 如果前面两种方式都不够存放大文件,则采用二级间接索引方式;
- 如果二级间接索引也不够存放大文件,这采用三级间接索引方式;
-
那么,文件头(Inode)就需要包含 13 个指针:
10 个指向数据块的指针;
第 11 个指向索引块的指针;
第 12 个指向二级索引块的指针;
第 13 个指向三级索引块的指针;
所以,这种方式能很灵活地支持小文件和大文件的存放: -
对于小文件使用直接查找的方式可减少索引数据块的开销;
-
对于大文件则以多级索引的方式来支持,所以大文件在访问数据块时需要大量查询;
-
这个方案就用在了 Linux Ext 2/3 文件系统里,虽然解决大文件的存储,但是对于大文件的访问,需要大量的查询,效率比较低。
比较
对空闲空间管理
空闲链表法:
使用链表对空间进行管理,每一个空闲块里有一个指针指向下一个空闲块,这样也能很方便的找到空闲块并管理起来
位图法
位图是利用二进制的一位来表示磁盘中一个盘块的使用情况,磁盘上所有的盘块都有一个二进制位与之对应。
当值为 0 时,表示对应的盘块空闲,值为 1 时,表示对应的盘块已分配。它形式如下:
1111110011111110001110110111111100111 …
在 Linux 文件系统就采用了位图的方式来管理空闲空间,不仅用于数据空闲块的管理,还用于 inode 空闲块的管理,因为 inode 也是存储在磁盘的,自然也要有对其管理。