首页 > 其他分享 >Lec 14 文件系统与设备

Lec 14 文件系统与设备

时间:2025-01-12 19:10:49浏览次数:1  
标签:文件 Lec 14 文件名 文件系统 磁盘 inode 目录

Lec 14 文件系统与设备

License

本内容版权归上海交通大学并行与分布式系统研究所所有
使用者可以将全部或部分本内容免费用于非商业用途
使用者在使用全部或部分本内容时请注明来源
资料来自上海交通大学并行与分布式系统研究所+材料名字
对于不遵守此声明或者其他违法使用本内容者,将依法保留追究权
本内容的发布采用 Creative Commons Attribution 4.0 License
完整文本

文件与系统

  • 文件是对数据的一种抽象

    • 文件的定义:有名字且持久化的一段数据
  • 文件系统

    • 提供了一组操作文件的API
  • UNIX系统API

    • OPEN, READ, WRITE, SEEK, CLOSE
    • FSYNC
    • STAT, CHMOD, CHOWN
    • RENAME, LINK, UNLINK, SYMLINK
    • MKDIR, CHDIR, CHROOT
    • MOUNT, UNMOUNT

img

INODE:文件的元数据

简单文件系统

  • 文件系统的特性与操作
    • 文件系统的特性
      • 文件数量固定:10 个文件
      • 文件名固定:从 “0”到“9”
      • 每个文件的大小固定为 4 KB
      • 10个文件在磁盘上是连续的
    • 文件系统的操作
      • 文件查找:文件名就是磁盘块号
      • 文件读写:即对相应磁盘块的读写
      • 文件删除:不支持

将磁盘抽象成一个大数组,块号为磁盘的索引,每个块的大小为4KB。
img

  • 改进简单文件系统
    • 增加文件的数量
    • 假设使用一个容量为 1 GB 的磁盘,最多保存 1 GB / 4 KB = 256 K个文件
  • 支持文件删除操作
    • 引入文件位图(bitmap),大小为256 × 1024 × 1b = 8 × 4KB = 32KB
    • 每个bit对应一个文件,若bit为0表示不存在,bit为1表示存在
    • 删除文件时,将该文件对应的bit设置为0

img

  • 仍然存在限制
    • 文件大小固定
      • 无法支持大于一个磁盘块(4KB)的文件
      • 文件系统依赖文件数据存储的连续性
    • 文件名固定
      • 只能用磁盘块号来表示文件名

引入inode

  • 引入inode:index node
    • 记录多个磁盘块号
    • 头部记录文件size信息
    • 每个文件对应一个inode
    • 称为文件元数据(Metadata)
  • 文件读写操作
    • 给定inode和文件内偏移(offset)
    • 根据offset计算出对应的磁盘块号
    • 若offset超出size则返回错误

img

  • inode表:记录所有inode

    • 可以看成inode的大数组
    • 每个inode使用inode号作为索引
    • 此时,inode号即为文件名
  • inode分配信息(位图)

    • 记录哪些inode已分配,哪些空闲
  • 超级块:Super Block

    • 记录磁盘块的大小、其他信息的起始磁盘块位置,等等
    • 是整个文件系统的元数据
  • 加载文件系统

    • 首先读取超级块,然后找到其他信息
  • 创建新文件

    • 根据inode分配信息找到空闲inode,将inode对应的bit设置为1
    • 返回inode在inode表中的索引,作为文件名
  • 查找文件(根据inode号)

    • 在inode表中根据inode号定位该inode
  • 删除文件

    • 在inode分配表中,将该inode对应的bit设置为0
  • 单级inode太大啦

  • 一个4GB的文件,对应inode有多大?

    • 假设磁盘块号(块指针)为8-Byte(64-bit)
    • inode大小:4GB/4KB * 8 = 8MB
    • 若文件大小为4TB,则inode大小为8GB!

img

  • 一个多级inode占用的空间很少。我们设计一个inode,假设如下:
    • 一共只有15个指针(即记录磁盘块),这些指针占用120-Byte
    • 包含12个直接指针,3个间接指针,1个二级间接指针
    • 文件最大为:4K x 12 + 4K x 512 x 3 + 4K x 512 x 512 = 48K + 6M + 1G
  • 如何支持更大的文件?
    • 可以启用三级索引,甚至四级索引
    • 与页表有所不同!页表储存的是虚拟地址到真实地址的转换索引,每一层级页表都会占用真实的物理空间。而磁盘的inode表(类似对应于0级页表)与磁盘数据区域是分开的,不会一同计算。
    • 格式化后,需要填写inode表指明每个磁盘的块,则超级块,存储块分配信息,inode分配信息和表格会占有一部分位置,因此会比表明的空间小一些。

目录也是文件

inode与文件名

  • inode本身已经包含了一个文件的所有信息
    • 可以使用inode号(inode表的索引)作为文件名
    • 给定一个inode号,就可以访问文件的所有数据
  • inode作为文件名的缺点
    • 名字很难记住,不够 user-friendly
    • 名字依赖于inode表位置的名字
    • 一旦改变了位置,就必须改变文件名
  • 以字符串作为文件名的好处
    • 在操作文件时,将文件的元数据隐藏起来,用户无需感知
    • 不依赖特定的存储设备
  • 如何实现字符串文件名到inode号的映射?
    • 使用映射表,记录字符串到inode号的映射
    • 将该表保存在一类特殊的文件中,称为目录文件
      • 目录本身也是一个文件,同样有inode
    • 复用inode机制来实现目录!

img

  • 目录中的每条映射称为一个目录项
    • 每一条目录项记录了一个inode号与文件名字符串的映射
    • 一个目录可以记录很多目录项
  • 目录文件的大小(占用空间)
    • 与其记录的文件大小无关
    • Q:与什么因素有关?
    • “目录” VS. “文件夹”
  • 目录支持查找操作
    • 给定一个目录文件和字符串
    • 在目录文件中查找字符串,并返回对应的inode
  • 目录中可以记录子目录,因为目录本身也是一个文件。
    • 通过“/”来分割父目录和子目录
  • 最顶端的目录没有目录名(文件名)
    • 被称为“根目录”(root)
    • 根目录没有文件名,在“/”的前面什么都没有
  • 绝对路径和相对路径
    • 绝对路径:如“/home/alice/test.md”
    • 相对路径:如“./test.md”

img

  1. 寻找根目录。我们的根目录在inode表中的第一个inode。
  2. 文件路径还没有结束,继续索引。inode-1的最后一项指向索引块。前往数据块33.
  3. 对数据块内存储的块分别进行寻找。在块31中,我们找到了os-book目录,需要回到inode表内去寻找对应的inode号。
  4. 回到inode表,找到inode号63内存储的数据块inode号。因为最后的是一个文件,因此逐个寻找对应。
  5. 在29号数据块内找到了对应的文件,其在inode表内存储为58号。
  6. 依次读取表内的数据块号,如果遇到了索引号则继续读取,直到文件读取结束。

img

img

软链接和硬链接

硬链接

  • 硬链接创建:ln命令
  • LINK
    • LINK("Mail/inbox/new-assignment", "assignment")
    • 将严格的层次结构(树)变成有向图
      • 注意:用户不能为目录创建link
    • 不同的文件名可以指向同一个inode号
  • UNLINK
    • 删掉从文件名到inode号的绑定关系
    • 如果 UNLINK 最后一个绑定,则把 inode 和对应的 blocks放到 free-list
      • 每个文件都需要一个 reference counter
  • 引用计数器(Reference count)
    • 一个 inode 可以绑定多个文件名
      • LINK 时 +1, UNLINK 时 -1
    • 当reference count为0时,文件被删除
    • 不允许出现环
      • 除了 '.' 和 '..'
      • 用来表明当前目录和上一层目录而不需要知道它们实际的名字

为什么LINK不能成环?
img

  • /a/b是一个目录,a的引用次数为1。a的inode号为25.
  • 执行LINK(/a/b/c, a),形成了一个环,a的引用次数为2。
  • 执行UNLINK(/a),删除了一条引用。因为a的引用次数为1,所以不能删除。这下谁也找不到inode 25了。

软链接

  • 软连接创建ln -s,windows好像叫做快捷方式。
  • 如何在一个磁盘上建立指向另一个磁盘的Link?
    • 无法,因为不同磁盘的 inode 命名空间是不同的(因为文件系统不同)
  • 一种简单的方案
    • 让inode在所有磁盘中是唯一的,显然不可行
  • 引入软链接(符号链接): soft link (symbolic link)
    • SYMLINK
    • 增加一种新的 inode 类型

img

  • 目录上下文转变的例子。设当前目录为Desktop。
  • 假设有一个目录: "./Scholarly/programs/www"
  • 目录下包含一个soft link
  • "./web" -> "./Scholarly/programs/www"
  • 运行如下命令
  • cd web
  • cd ..
  • 当前是哪个目录?
    • Desktop
  • cd -p ..
    • programs

img

文件系统的细节

  • 文件名并不是文件的一部分
    • 文件名不是文件的数据,也不是文件的元数据(inode)
    • 文件名是目录的数据,是文件系统的元数据
    • 一个inode可以有多个文件名(硬链接)
  • 每个硬链接的地位都是相同的
    • 文件名就是硬链接(而不是一个文件名,一个链接名)
  • 目录所占磁盘空间通常是很小的
    • 目录仅仅负责记录文件名到inode号的映射
    • "文件夹"这个名字有一定的误导性

文件系统API

  • 应用程序通过系统调用使用这些 API
    • CHDIR, MKDIR, RMDIR
    • CREAT, LINK, UNLINK, RENAME
    • SYMLINK
    • MOUNT, UNMOUNT
    • OPEN, READ, WRITE, CLOSE
    • SYNC
  • 文件系统的两类元数据
    • 磁盘上文件的元数据:静态的、在磁盘中
    • 被打开文件的元数据:动态的、在内存中

文件的元数据(磁盘中)

  • 拥有者/所在组 ID
    • 拥有该 inode 的 用户 ID 和 组 ID
  • 权限的类型
    • 拥有者、所在组、其他
    • 读、写、执行
  • 时间戳
    • 最后一次访问 (如:READ 操作)
    • 最后一次修改 (如:WRITE 操作)
    • 最后一次 inode 更新 (如:LINK 操作)

POSIX定义的部分文件元数据
img

被打开文件的元数据(内存中)

  • 整个系统维护了一个 file_table
    • 记录了所有打开的文件的信息
    • 包括:文件游标(file cursor)、引用数(ref_count)
    • 父子进程间可以共享文件游标
  • 每个进程维护了一个 fd_table
    • 记录了该进程每个 fd 所对应文件在 file_table 中的索引
  • 文件游标
    • 记录了一个文件中下一次操作的位置
    • 可以通过 SEEK 操作修改
  • 情况 1: 共享游标
    • 父进程将 fd 传递给子进程
      • UNIX 中,子进程会继承父进程所有已经打开的 fd
    • 允许父子进程共享同一个文件
  • 情况 2: 非共享游标
    • 两个不同的进程打开同一个文件

img

  • write() 与 read() 类似

    • 可能需要分配新的 block
    • 更新 inode 的 size 和 mtime
  • close()

    • 释放 fd_table 中的相关项
    • 减小 file table 中相关项的 refcnt
    • 如果 file table 中相关项 refcnt 为 0,则将其释放
  • 删除一个打开的文件

  • 进程P1打开了文件 A

    • 运行 open,在 file_table 和 fd_table 中都增加了一项
  • 进程P2将文件 A 删除

    • 删掉了指向文件 A 的最后一个目录项
    • 文件 A 的 inode 引用数变成了 0
  • 文件 A 的 inode 不会被立即释放和删除

    • 直到前一个进程调用 close 将其关闭
    • (在 Windows 上,则通过"禁止删除打开的文件"实现类似效果)
  • fsync

  • Block cache

    • 缓存了最近被使用的磁盘块
    • 缓存缺失时,从磁盘中读取
    • 推迟数据向磁盘的写入
    • 寻求机会批量写入,提升性能
    • 问题:如果在写入前发生故障,可能会造成不一致
  • SYNC

    • 保证对文件的所有修改被写入到存储设备

img

文件系统的崩溃一致性

  • 文件系统中保存了多种数据结构
  • 各种数据结构之间存在依赖关系与一致性要求
    • inode中保存的文件大小,应该与其索引中保存的数据块个数相匹配
    • inode中保存的链接数,应与指向其的目录项个数相同
    • 超级块中保存的文件系统大小,应该与文件系统所管理的空间大小相同
    • 所有inode分配表中标记为空闲的inode均未被使用;标记为已用的inode均可以通过文件系统操作访问
  • 突发状况(崩溃)可能会造成这些一致性被打破!

img

  • 重启并恢复后
  1. 维护文件系统数据结构的内部的不变量
    例如, 没有磁盘块既在free list中也在一个文件中
  2. 仅有最近的一些操作没有被保存到磁盘中
  3. 没有顺序的异常
  • 方法一:同步元数据写+fsck

  • 同步元数据写

    • 每次元数据写入后,运行sync()保证更新后的元数据入盘
  • 若非正常重启,则运行fsck检查磁盘,具体步骤:

    • 检查superblock
      • 例:保证文件系统大小大于已分配的磁盘块总和
      • 如果出错,则尝试使用superblock的备份
    • 检查空闲的block
      • 扫描所有inode的所有包含的磁盘块
      • 用扫描结果来检验磁盘块的bitmap
      • 对inode bitmap也用类似方法
    • 检查inode的状态
      • 检查类型:如普通文件、目录、符号链接等
      • 若类型错误,则清除掉inode以及对应的bitmap
    • 检查inode链接
      • 扫描整个文件系统树,核对文件链接的数量
      • 如果某个inode存在但不在任何一个目录,则放到/lost+found
    • 检查重复磁盘块
      • 如:两个inode指向同一个磁盘块
      • 如果一个inode明显有问题则删掉,否则复制磁盘块一边给一个
    • 检查坏的磁盘块ID
      • 如:指向超出磁盘空间的ID
    • 检查目录
      • 这是fsck对数据有更多语义的唯一的一种文件
      • 保证 . 和 .. 是位于头部的目录项
      • 保证目录的链接数只能是1个
      • 保证目录中不会有相同的文件名
  • 问题:方法一太慢了,同步元数据写导致创建文件操作非常慢

  • 方法二:日志(journaling)

  • 在进行修改之前,先将修改记录到日志中

    • 如:如何修改block-bitmap、如何修改data
  • 所有要进行的修改都记录完毕后,提交日志

  • 确定日志落盘后,再修改数据和元数据

  • 修改完成后,删除日志

  • example: Ext4的日志

  • Data mode(即 full journaling)

    • 数据和元数据都写入日志区域
  • Ordered mode(默认配置)

    • 先写数据(原本的文件位置),再写元数据(日志)
  • Writeback mode

    • 仅仅将元数据写入日志
    • 数据依然写入原本的位置
    • 日志和数据之间没有顺序保证

img

  • 崩溃后基于日志恢复
  • 启动后首先检查日志区域
    • 若没有任何日志记录,则无需恢复
  • 扫描所有已经COMMIT的事务
    • 若没有COMMIT的事务,则无需恢复
    • 对已经COMMIT的事务,将元数据从日志区写到原本位置
  • 完成后清空日志区域

标签:文件,Lec,14,文件名,文件系统,磁盘,inode,目录
From: https://www.cnblogs.com/mumujun12345/p/18667178

相关文章

  • day14-Linux系统基础权限知识精讲
    1.给文件加特殊属性1.1chattra:只能追加内容,不能删除i:不能修改,不能删除;保护关键文件,防止非法写入[root@oldboy~]#chattr+atest.txt[root@oldboy~]#chattr+itest.txt[root@oldboy~]#echo123>>test.txt-bash:test.txt:权限不够[root@oldboy~]......
  • (14-2)基于Latent Diffusion Transformer的文生视频系统:系统配置
    6.3 系统配置在“configs”目录中,保存了本项目中涉及的不同数据集和任务提供配置文件。这些配置文件定义了模型的训练、验证和测试过程中的关键参数和设置,包括网络结构、优化器参数、学习率调度、数据预处理方式等。目录中每个子文件夹或文件的命名(如ffs、sky、t2x、taich......
  • Lec 13 同步原语
    Lec13同步原语License本内容版权归上海交通大学并行与分布式系统研究所所有使用者可以将全部或部分本内容免费用于非商业用途使用者在使用全部或部分本内容时请注明来源资料来自上海交通大学并行与分布式系统研究所+材料名字对于不遵守此声明或者其他违法使用本内容者,将依......
  • Lec 12 进程间通信
    Lec12进程间通信License本内容版权归上海交通大学并行与分布式系统研究所所有使用者可以将全部或部分本内容免费用于非商业用途使用者在使用全部或部分本内容时请注明来源资料来自上海交通大学并行与分布式系统研究所+材料名字对于不遵守此声明或者其他违法使用本内容者,将......
  • Life Long Learning(李宏毅)机器学习 2023 Spring HW14 (Boss Baseline)
    1.终身学习简介神经网络的典型应用场景是,我们有一个固定的数据集,在其上训练并获得模型参数,然后将模型应用于特定任务而无需进一步更改模型参数。然而,在许多实际工程应用中,常见的情况是系统可以不断地获取新数据,例如Web应用程序中的新用户数据或自动驾驶中的新驾驶数据。......
  • collections.OrderedDict
    在Python的collections模块中,OrderedDict是一个非常有用的类,它是一个字典的子类,能够记住元素插入的顺序。这在需要保持键值对顺序的场景中非常有用,尤其是在处理需要顺序操作的数据时。可以像创建普通字典一样创建OrderedDict,但OrderedDict会记住元素插入的顺序#创建一个空的Ord......
  • LeetCode热题100(二十六) —— 142.环形链表II
    LeetCode热题100(二十六)——142.环形链表II题目描述代码实现思路解析你好,我是杨十一,一名热爱健身的程序员在Coding的征程中,不断探索与成长LeetCode热题100——刷题记录(不定期更新)此系列文章用于记录我在学习LeetCode热题100过程中的总结和收获愿与诸君共同探讨,在......
  • 代码随想录算法训练营第4天 | 24. 两两交换链表中的节点,19.删除链表的倒数第N个节点,面
    一、刷题部分1.124.两两交换链表中的节点原文链接:代码随想录题目链接:24.两两交换链表中的节点-力扣(LeetCode)1.1.1题目描述给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。示例1:输......
  • Lec 11 调度
    Lec11处理器调度License本内容版权归上海交通大学并行与分布式系统研究所所有使用者可以将全部或部分本内容免费用于非商业用途使用者在使用全部或部分本内容时请注明来源资料来自上海交通大学并行与分布式系统研究所+材料名字对于不遵守此声明或者其他违法使用本内容者,将......
  • Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统
    引言在嵌入式Linux开发中,网络加载内核、设备树和根文件系统是一种常见的方法。这种方法通常用于开发和调试阶段,允许开发者快速更新和测试内核及文件系统。本文将详细介绍如何在Ubuntu20.04上搭建环境,以支持嵌入式Linux的网络加载。前提条件Ubuntu20.04系统。已安装的TFTP服......