File Management

1. 文件系统

1.1. 文件

1.2. 文件系统

操作系统中负责存取和管理信息的模块

观察文件, 需要观察它的两个部分

  • 逻辑结构 (逻辑文件)
  • 存储结构 (物理文件)

文件系统的功能

由于文件是一种抽象的概念, 因此文件系统的功能也要分层次考虑

面向用户的功能

  • 文件的按名存取 (这也是文件系统的主要目的)
  • 文件的共享和保护
  • 文件的操作和使用

为了构建可靠的文件系统, OS必须考虑的事情是

  • 文件目录的建立和维护
  • 存储空间的分配和回收
  • 数据的保密和保护
  • 监督用户存取和修改文件的权限
  • 实现在不同存储介质上信息的表示方 式编址方法存储次序以及信息 检索等问题

2. 文件的组织

2.1. 文件的存储

文件存储介质有磁带光盘和磁盘

两个概念: 卷和块

卷 (Volume): 一个卷可以视为一个文件系统. 从设计的角度来讲, 一个Volume可以认为是一个虚拟存储设备(磁盘/光盘/磁带). 在Windows上, 一个物理磁盘实际上可以分为多个Volume, 每个Volume可以使用不同的文件系统(NTFS, FAT, etc.)

块 (Block): Block是存储器进行数据交换的最小单位. 早期的Block大小一半是512字节, 但是现代Block的大小在4kb~64kb之间

块为什么设计成这么大: 考虑多方面的统计学因素. 实际上, 块的大小很灵活. 同一存储介质的块大小一般相同, 也可以不同(这话说了就像没说)

块是连续存储的吗: 是也不是. 实际上, 块之间留有空隙. 考虑到如下的2点因素

  • 设备读写时往往会进行机械操作, 为了确保安全并避免数据损坏相邻的数据块之间需要留有足够的距离以免机械部件运动产生干扰或碰撞
  • 某些外围设备可能需要识别不同块之间的分界点以便正确地读取或写入数据为了满足这种需求相邻的数据块之间也会留有一定的间隙以确保设备能够准确识别块的边界位置

顺序存取存储设备的信息安排

磁带 & 光盘是典型的顺序存取存储设备

严格依赖信息的物理位置次 序进行定位和读写的存储设备

直接存取存储设备的信息安排

磁盘

它的每个物理记录有确定的位置和唯 一的地址存取任何一个物理块所需 的时间几乎不依赖于此信息的位置

2.2. 文件的逻辑结构

逻辑文件

i.e.文件的逻辑结构. 也就是完全不管其物理结构的, 用户能够直观感受到的文件

分成两种形式

  • 流式文件 (Stream File)
  • 记录式文件 (Record File)

GPT: 判断一种文件是流式文件还是记录式文件需要根据该文件所采用的文件格式和数据组织方式来进行分析

通常情况下流式文件是一种顺序型文件其中数据按照固定的字节流顺序排列在读写流式文件时应用程序可以读取或写入任意长度的数据但必须按照顺序进行不能跳过或插入数据

而记录式文件则通常将数据组织成若干个逻辑上的记录每个记录由多个字段组成在处理记录式文件时应用程序通常需要对每个记录进行读取或写入操作并且每个记录通常具有相同的长度或可变长度由特定的记录分隔符进行分隔

例如在文本文件中每个字符都被视为一个字节它们按照顺序排列组成了一整个文件因此文本文件是一种典型的流式文件而在数据库系统中每个记录代表一个实体例如一个人一辆车或一张订单等等每个记录由若干个字段组成因此数据库中的数据通常是一种记录式文件

总之要判断一个文件是流式文件还是记录式文件需要分析该文件所采用的文件格式和数据组织方式

直观的感受: 有结构的文件就是记录式文件, 无结构的文件就是流式文件

文件系统和数据库系统的区别

DBMS可以支持基于联系的查询 (因为数据库中的记录可以通过数据冗余形成某种联系). 但是文件系统不能支持基于联系的查询

2.3. 记录的成组与分解

这里的记录就是上文 记录式文件记录

给出非常愚蠢的定义: 若干个逻辑记录合并成一组写入一个块叫记录的成组每块中的逻辑记录数称为块因子

如何实现记录成组: 使用计算机科学中的经典想法——添加一个中间层(buffer)

  • 记录的成组操作在输出缓冲区内进行 凑满一块后才将缓冲区内的信息写到存储介质上

类似的, 先从存储介质上取出一个block, 再取出其中的一个记录, 这样的行为叫做记录的分解

记录成组和分解的优点

  • trivially 节省了存储空间 (考虑到存储设备一次性只能传一个block过来, 如果记录不成组的话, 一个block中便只能有一条记录, 是非常浪费的)
  • trivially 减少IO次数

当然也带来一些不足一提的副作用:

  • 提前读: 读取一个逻辑记录时, 会将和它在一个block的一堆逻辑记录都带出来
  • 推迟写: 写完一个逻辑记录后, 需要将它后续的一堆逻辑记录都写完并构成一个完整的block才能写入存储设备

2.4. 文件的物理结构

文件的物理结构 $\iff$ 物理文件

从设计的角度来讲, 文件的物理结构影响文件系统的性能

顺序文件

$O(n)$

将逻辑上连续的文件存放到存储介质中相邻的block中, 以这样存储方式进行存储的文件叫做顺序文件(连续文件). 一些典型的例子就是系统文件和批处理文件(bat, sh)

trivially, 顺序文件的存储是很快的, 但是任何修改都会显得很麻烦(可能会影响相邻的文件), 同时在存储之前必须先知道文件的大小. 因此从设计的角度来讲, 多读少写的文件更加适合以这样的方式存储. 系统文件就是很典型的例子.

从设计的角度来讲, 顺序文件的存储很像C语言里的数组.

连接文件

$O(n)$, 或者叫串联文件

愚蠢的又平凡定义: 用一个叫连接块的东西, 来指向下一个物理块 (因为物理块是最小单位). 同时如果连接块的value为0, 它就是结尾

我真不理解为什么要设置这么多混淆的, 矛盾的, 愚蠢的, 不可复用的定义.

从设计的角度来讲, 顺序文件的存储很像C语言里的链表. 它的存储, 修改, 删除都非常方便, 但是不方便的是一切涉及到的操作. 并且由于其物理结构的性质, 只能顺序存取

直接文件

$O(1)$, 或者叫散列文件

通过计算记录的关键字建立与其物理存储地址之间的对应关系, 常常使用Hash散列. 那么很明显, 这样的文件应该具有Hash散列数据的性质.

为了解决Hash函数中不可避免的冲突, 这里引入几个无比trivial又中二的称呼:

  • 拉链法
  • 循环探查法
  • 二次散列法
  • 溢出区法

索引文件

$O(1)$, 基本思想: 建立一个中间层

索引文件在文件存储器上分两个区

  • 索引区
  • 数据区

访问索引文件需两步操作

  • 第一步查找索引表
  • 第二步获得记录物理地址

为每个文件建立了一张索引表其中每个表目包含一个记录的键(或逻辑记录号)及其存储地址. 这样的设计是我很欣赏的.

在Unix下, 可以用stat <PATH> 来查看文件的索引结构

stat

3. 文件目录

3.1. 目录结构

文件目录是实现文件的 按名存取 的关键数据结构. 为了解决不同用户文件的 命名冲突 问题通常在文件系统中采用多级目录.

具体来说, Unix系统中, 通过 目录项 这一数据结构实现文件系统的按名存取功能.

比较重要的一点是, 文件目录需要永久保存因此也组织成文件存放在磁盘上目录文件

  • 一级目录结构: 想象一下所有文件存储在一个目录下
  • 二级目录结构: 底层目录用于存储不同的用户信息, 高级目录用户存储每个用户的文件 (很有点RBAC的感觉)
  • 树形目录结构

值得注意的是, 在树形目录结构中, 一个文件的全名包括从根目录开始到文件为止, 通路上遇到的所有子目录路径, 又称为路径名

也就是说路径名不是路径的名字, 是这个文件的名字

值得区分的是, 目录和路径是不一样的概念:

  • 目录Directory是指在文件系统中用于组织和管理文件和子目录的一种数据结构每个目录都可以包含若干个文件和子目录并且可以通过目录索引来访问其中的内容在Unix和Linux等操作系统中目录通常用一个特殊的文件来表示其中存储了目录下的所有文件和子目录信息
  • 路径Path是指用于标识文件或目录在文件系统中位置的字符串通常以根目录/为起点逐级列出该文件或目录所在的目录名直到最后一级为止例如/usr/local/bin/test.sh就是一个典型的文件路径表示test.sh文件位于/usr/local/bin目录下

文件系统用**目录来组织文件**

3.2. 文件目录的管理

这里前面一部分主要讲一些指令, trivial

树形文件系统存在的一个问题是当一个文件经过许多目录节点时, 使用很不方便; 系统在沿路径查找目录时, 往往要多次访问文件存储器使访问速度大大减慢.

从设计的角度来讲, 一种有效办法是把常用正在使用的那些文件目录复制进主存, 这样, 既不增加太多的主存开销. 又可明显减少目录查找时间.

为了实现如上的设计, 设计一种新的中间层, 叫做活动文件表, 抽象出文件的两种平凡的操作:

  • 打开: 系统可以为每个用户进程建立一张活动文件表当用户使用一个文件之前先通过 打开 操作把该文件有关目录信息复制到指定主存区域, 有关信息填入活动文件表, 以建立用户进程该文件索引的联系. (这也就是大文件打开时间会比较长, 特别大的文件打开时可能会死机)
  • 关闭: 当不再使用该文件时使用 关闭, 切断用户进程和这个文件的联系. 同时, 若该目录已被修改过则应更新辅存中对应的文件目录

4. 文件共享, 保护和保密

从信息安全 (CIA) 的角度, 文件的设计需要考虑如下几点

  • 文件共享: 是指不同用户共同使用某些文件 (Accessibility)
  • 文件保护: 是指防止文件被破坏 (Integrity)
  • 文件保密: 则是指防止文件及其内容被其他用户窃取 (Confidentiality)

4.1. 共享

很自然地, 操作系统必须为文件共享提供并发控制. 这一点我们会在并发部分仔细谈论.

4.2. 保护

常用的文件保护办法

文件副本

  • 动态多副本技术: 是在多个介质上维持同一内容的文件并且在更新内容时同时进行
  • 转储, 备份与恢复: 定时把文件复制转储到其它介质上当某介质上出现故障时复原转储文件

文件存取矩阵与文件存取表

也就是信息安全课上讲的那个

实际上限制了用户能访问文件的部分权限, 是一种RBAC

设计文件属性

rwx, user等信息便是非常典型的文件属性. 使用chmod, chgrp, chown等指令便可以修改对应的文件属性.

5. 文件的使用

5.1. 存取方法

文件存取方法是操作系统为用户程序提供的使用文件的技术和手段, 在某种程度上依赖于文件的物理结构.

顺序存取

$O(n)$

指的是像磁带这种存储设备上, 想要读或者写某一个文件, 必须从头扫描找到它.

直接存取

$O(1)$, 也叫做随机存取

指的是按地址索引. 可以直接访问存储空间内任何一处的数据. 典型的例子就是磁盘上的文件, 既可以随机存取, 又可以顺序存取

索引存取

$O(1)$, idk, or maybe $O(\log n)$

要查表. 一般按照二分查找等方法索引.

5.2. 文件的使用

用户通过两类接口来与文件系统相联系.

  • 文件操作命令: cp, mv, find, mkdir, etc.
  • 文件类系统调用: 建立, 打开, 读/写, 定位, 关闭, 撤销

建立文件: 在相应设备上建立一个文件目录项, 为文件分配第一个物理块, 在活动文件表中申请一个项, 登记有关目录信息, 并返回一个文件句柄

撤销文件: 若文件没有关闭, 先关闭文件; 若为共享文件, 进行联访处理; 在目录文件中删去相应目录项; 释放文件占用的文件存储空间

打开文件: 将活动文件表中该文件的当前 使用用户数减1若此值为0则收回此活 动文件表完成推迟写 若活动文件表 目内容已被改过则应先将表目内容写回文 件存储器上相应表目中以使文件目录保持 最新状态

Unix下打开文件

而open的返回值是一个整数类型的文件描述符 (File Descriptor)

读/写文件: 按文件句柄从活动文件表中找到该文件的目录项信息; 根据目录项指出的该文件的逻辑和物理组织方式, 把相关逻辑记录转换成物理块

定位文件

6. 文件系统实现

6.1. 辅存空间管理

主要是碎片管理: 由于被多用户共享, 文件碎片经常出现.

解决方法: 定期地对文件重新组织让其存放在连续存储区中. (trivial but necessary)

辅存空间的分配方式

  • 连续分配存放在辅存空间连续存储区中 (连续的物理块号) 优点是顺序访问时速度快管理较为简单 但为了获得足够大的连续存储区需定时进行‘碎片’整理
  • 非连续分配动态分配给若干扇区或簇几 个连续扇区不要求连续优点是辅存空间管理效率高便于文件动态增长和收缩

空闲块的管理

  • 位示图法: FAT12文件系统
  • 空闲块成组连接法: 使用如下图的方式将空闲块组织起来

6.2. 文件系统的实现层次