🌦️ 文件管理
2022年10月10日
- os
🌦️ 文件管理
1. Linux 文件系统的组成
- 文件系统的基本数据单位是 文件
- 目的:对磁盘上的文件进行组织管理
- 每个文件均包含 索引节点 [
index node
] & 目录项 [directory entry
] 两部分
index node
1) 索引节点 - 作用
- 存储文件的元信息
- 元信息有哪些
- inode 编号
- 文件大小
- 创建时间
- 修改时间
- 磁盘位置
- 访问权限
- 查看命令
stat 文件名
- inode 编号
- 每个文件的 inode 号码是唯一的
- 当移动 | 重命名文件时,inode 号码不变
- 根据文件名打开文件流程:
- 根据文件名找到对应的 inode 号码
- 根据 inode 号码获取 索引节点 信息,进行权限认证等操作
- 根据 索引节点 信息,找到文件数据对应的 硬盘存储块位置,读出数据
- 硬盘格式化后,会被分成以下几个区域:
- 超级块区
- 存储文件系统的相关系统
- 例如:块的大小、块的个数等
- 当文件系统被挂载时,加载进内存
- 索引节点区
- 存储索引节点相关信息
- 每个索引节点一般为 128 B | 256 B
- 对于硬盘上的数据,一般每 1KB | 2KB 均需要设置一个 索引节点
- 为了加速查询,一般把索引数据缓存到内存中
- 当文件被访问时,加载进内存
- 数据块区
- 真正存储磁盘数据的位置
- 超级块区
- 文件在磁盘中的存储
- 磁盘读写的基本单位是 扇区,一个 扇区 == 512 B
- 多个扇区组成一个逻辑块,由于扇区太小,所以实际每次读写以 逻辑块 为单位
- Linux 中一个逻辑块 == 8 扇区 == 4 KB
directory entry
2) 目录项 - 目录
- 在 Linux 中目录也是一种文件
- 打开目录就是打开目录文件
- 目录存储在磁盘
- 目录中存放的是目录下的文件信息,例如 文件名、文件类型等
- 具体文件信息通过
Hash
索引的方式存储,提高当前目录下文件查找效率,不过需要额外措施防止 hash 冲突
文件 inode 号 | 文件类型 | 文件名 |
95827 | 目录 | . |
95828 | 目录 | .. |
hash 索引 | 数据块指针 | |
3269874FE1236EA6 | 66 | |
BF05674FE1236EA6 | 103 | |
…… | …… |
- 目录项
- 为了避免频繁从磁盘中读取目录,内核将已经度过的目录用 目录项 这个数据结构缓存在内存中
- 当下次读到相同目录时,直接从内存读,从而提高读取速度
- 包含哪些内容
- 文件的名称
- 文件的类型
- 索引节点指针
- 与其他目录项的层级关系
2. 虚拟文件系统 VFS
1) 作用
- 文件系统根据文件组成方式的不同,形成了不同的文件系统
- 为了简化用户对文件系统的访问,在用户层 & 不同文件系统之间添加了 虚拟文件系统
- 为用户提供统一接口
2) 常见文件系统
- 磁盘文件系统
- 直接将数据存储在磁盘中
- 例: Ext 2/3/4, XFS
- 内存文件系统
- 数据存储在内存空间
- 例:
/proc
&/sys
- 网络文件系统
- 访问其他主机数据的文件系统
- 例: NFS, SMB
3. 文件的存储
- 文件系统的基本操作单位是 数据块,而非字节流等
- 文件在磁盘中的存储分为以下两种存放方式:
- 连续空间存储
- 非连续空间存储
1) 连续空间存储
- 特点
- 文件存放在连续的物理空间中,需要确定文件大小才可分配空间
- 优点
- 读写效率高,磁盘一次寻址即可定位到文件
- 缺点
- 易产生碎片化空间,空间利用率低
- 文件扩容可能出现扩容失败,从而重新移动整个文件到新的位置
2) 非连续空间存储
- 链表
- 隐式链表
- 文件头包含 起始块 & 末尾块 的位置,且每个数据块中存储一个
next
指针,指向下一个数据块的位置 - 在磁盘中依次查找所有数据库,速度较慢
- 若某个数据块的 next 指针出现问题,会导致整个文件的损坏
- 需要额外空间存储 next 指针
- 文件头包含 起始块 & 末尾块 的位置,且每个数据块中存储一个
- 显式链表
- 将每个数据块的
next
指针存放在 文件分配表 中,文件分配表存在于 内存 - 内存查找,比磁盘访问速度要快
- 若磁盘很大,则文件分配表也很大,不适用于该情况
- 将每个数据块的
- 特点
- 不会产生磁盘碎片,空间利用率高
- 动态扩容方便
- 需要经过多次磁盘查找
- 隐式链表
- 索引
- 实现:
- 文件头包含 索引数据块 的指针
- 每个文件均有自己的 索引数据块,索引数据块中存储该文件用到的所有数据块的 指针列表,索引数据块也存放于磁盘中
- 通过索引数据块中的指针列表,依次查找磁盘中的数据块
- 特点:
- 不会产生磁盘碎片,空间利用率高
- 动态扩容方便
- 支持顺序读写 & 随机读写
- 需要经过多次磁盘查找
- 不论文件多大,均有对应的 索引数据块;当文件占用数据块过多时,一个 索引数据块 可能存放不下,此时需要进行改进
- 如何改进从而存放大数据?
- 索引 + 链表
- 在索引块中添加 next 指针,指向下一个索引数据块
- 多级索引
- 一个索引块中存放多个索引块的位置
- 其他索引块中存放部分数据块指针
- 索引 + 链表
- 实现:
3) Unix 文件系统早期的文件存储方式
- 文件头中包含 13 个指针
- 10 个指向数据块的指针
- 当文件占用数据块 <= 10 时,直接存放在这里,可以通过直接查找方式找到文件存储地址
- 1 个指向 一级索引 的指针
- 当文件占用数据块 > 10 && 只用 一级索引 就可以存放所有数据块 指针时,可以通过一级索引方式查找,一级索引中存放的是 所有数据块 指针列表
- 1 个指向 二级索引 的指针
- 当文件占用数据块可以用 二级索引 盛下时,二级索引 存放 所有索引块的指针列表,找到每个索引块后,可以得到该索引块中存放的 部分数据块 指针
- 1 个指向 三级索引 的指针
- 10 个指向数据块的指针
4) 空闲空间的管理
- 如何在存储文件时,确定哪里有空闲的数据块可以存储该文件
① 空闲表
- 动态维护一张表
- 表中每行存储空闲块的 开始位置 & 空闲长度
- 当请求分配磁盘空间时,
- 系统一次扫描空闲表中的行,直到找到满足条件的第一个空闲区间段
- 当用户撤销一个文件时,
- 回收文件系统空间
- 顺序扫描空闲表,确定插入 | 更新位置,进行更新
- 特点:
- 适用于空闲区较少的情况
② 空闲链表
- 将空闲数据块通过 next 指针连接
- 当请求分配磁盘空间时,
- 从链表头开始依次选取需要的空闲数据块
- 特点:
- 不支持随机访问
- 适用于空闲区较少的情况
③ 位图法
- 用二进制的一位表示磁盘中该数据块的使用情况
- 当 == 0 时,说明该数据块空闲
- 当 == 1 时,说明该数据块已被分配
- 特点:
- 简单方便
- Linux 中采用该种方式,还用于 inode 空闲块的管理
- 单个位图计算
- 一个位图假设占用一个数据块,一个数据块
== 4 KB
- 一个位图可以记录的数据块个数 =
= 4 KB = 4 * 1024 * 8 = 2 ^ 15
- 一个位图可以记录的数据块总大小
== 2 ^ 15 * 4 KB = 127 MB
- 一个位图假设占用一个数据块,一个数据块
- Linux 中采用块组的方式存放多个位图,每个块组记录一个位图大小的数据块
4. 其他问题
1) 硬连接 VS 软连接
- 硬连接
- 文件别名不同,但是
inode
节点是同一个,因此指向的是同一个磁盘上的文件,通过任意一个文件修改内容,另一个读取到的是修改后的内容 - 由于
inode
节点不可跨文件系统,因此硬连接的文件也是不可跨文件系统的 - 当要删除 inode 节点对应的文件时,需要删除所有该 inode 节点对应的硬连接 & 源文件,才会彻底删除该文件
- 文件别名不同,但是
- 软连接
- 基于源文件创建一个新文件,该新文件有自己的
inode
索引节点,只不过内容存放的是源文件的路径,类似于 Windows 下的快捷方式 - 所以访问该新文件时,通过里面存放的源文件路径,间接访问到了源文件的内容
- 由于
inode
节点是新的,因此可以跨文件系统 - 当删除源文件时,新文件仍存在,只不过通过文件中存放的路径,找不到源文件而已
- 基于源文件创建一个新文件,该新文件有自己的
- 命令
ln [选项] 源文件 目标文件
- 选项包括:
-s
建立软连接,不加则建立硬连接-f
若目标文件已存在,则删除目标文件后,再建立相应连接