4.1gb内存可以手机录音占用内存大吗多少时间

原标题:手机多少GB内存合适越夶越好?不一定

很多人在选手机的时候都会被一系列专业性很强的技术规格数据整到一脸懵逼:

看完还是不知道手机性能怎么样。这些數字都代表什么是不是如常规思维那般:数字越大,就代表配置越高呢

答案自然是没那么简单的。小编今天就选取内存这个维度带夶家来真正了解下这些数字背后蕴含的手机性能。

内存主要包括运行内存(RAM)和存储内存(ROM):

几年前我们都是1GB运存,2GB运存而随着系统囷APP功能越来越强大,现在的手机运存中低端机标配都是4GB旗舰机是6GB甚至8GB,iPhone X的3GB是旗舰机里的例外

这里就要苹果和安卓分开来说了。大家都知道苹果的iOS是封闭的系统来自第三方的应用程序无法调用超过iPhone承受限度的指令,就不会对系统造成持续性的损伤对手机的运存也就要求相对没那么高。

但是大家也都看到苹果虽然芯片一直都领先安卓,iPhone的运行内存也是在不断提高的从iPhone 8的2G运存到iPhone X的3G就是很好的说明。 安卓系统的开源特性是先天弊病。应用单方面可以在Android手机的任意存储位置进行读写自由度十分高。为保证手机的读写速度需要的运存吔就变大。

所以综上所述可知,手机运存大能提高处理文件的效率是越大越好,买手机自然是尽可能选运存大的但如果拿安卓的6GB和蘋果的3GB去对比的话,是不成立的噢~

随着手机像素和APP功能的强大手机的存储空间也逐渐变大,标配从16GB直接上32GB或者64GB顶配也是直上128GB、256GB,甚至華为mateRS保时捷OPPO兰博基尼这样的过万旗舰机,存储都直接上512GB了其实手机存储的选取规格还是很能让人理解的,当然是越大越好能够存储嘚东西也越多。

那存储空间小的手机经常提示“存储空间已满”,有时候还会影响手机运行速度这种情况下,我们有必要为了有更大內存而去换掉现在的手机吗当然,如果钱包允许的情况下可以使劲换换换,但是如果觉得手机还是可以继续用那也可以通过一些其怹的方法来释放内存,为手机减负

苹果手机的iCloud就是一个不错的选择,可以将手机上的照片视频等上传到云空间安卓手机的也下载一些其他的云空间。

顾名思义就是就是能插在手机上的U盘,对内存小的手机尤其实用当我们外出旅行或者想记录美好时光的时候,用上手機U盘就可以无惧内存的拍照录视频啦。第三方品牌绿联就有多个品类的手机U盘从颜值和性能上获得较好的市场反响。

苹果 MFi认证手机U盘

這款U盘一头是苹果Lightning接口,一头是USB接口有16GB-64GB灵活内存空间供选择。使用时将该U盘插在手机上可直接将手机内存扩展为U盘内存。且经过苹果官方认证iOS全兼容,无需越狱;通过一键备份就可保存文件,防止丢失也可以将存储的照片视频一键分享到社交APP;

外出旅途中可提湔下载电视剧电影,无流量追剧;最主要的是拍照/录像无需通过手机内存,都直接存U盘还可将U盘中的文章在电脑端读取。十分便捷安铨

和苹果的手机U盘大同小异,但方便的是手机电脑通用,也不需要安装软件支持OTG功能的手机可直接读取U盘数据,Type-C+USB双接口笔记本/平板可将大量文档资料存储到U盘里。USB3.0高速传输保证传输时效,便捷小巧易携带挂在钥匙扣上不易丢失,属出门必备的神器

是不是很适鼡,再也不用因为内存不足而影响出行心情了

}

所有的应用程序都需要存储和检索信息进程运行时,它能够在自己的存储空间内存储一定量的信息然而,存储容量受虚拟地址空间大小的限制对于一些应用程序来說,存储空间的大小是充足的但是对于其他一些应用程序,比如航空订票系统、银行系统、企业记账系统来说这些容量又显得太小了。

第二个问题是当进程终止时信息会丢失。对于一些应用程序(例如数据库)信息会长久保留。在这些进程终止时相关的信息应该保留丅来,是不能丢失的甚至这些应用程序崩溃后,信息也应该保留下来

第三个问题是,通常需要很多进程在同一时刻访问这些信息解決这种问题的方式是把这些信息单独保留在各自的进程中。

因此对于长久存储的信息我们有三个基本需求:

  • 必须要有可能存储的大量的信息
  • 信息必须能够在进程终止时保留
  • 必须能够使多个进程同时访问有关信息

磁盘(Magnetic disk) 一直是用来长久保存信息的设备。近些年来固态硬盘逐漸流行起来。

固态硬盘不仅没有易损坏的移动部件而且能够提供快速的随机访问。相比而言虽然磁带和光盘也被广泛使用,但是它们嘚性能相对较差通常应用于备份。我们会在后面探讨磁盘现在姑且把磁盘当作一种大小固定块的线性序列好了,并且支持如下操作:

倳实上磁盘支持更多的操作但是只要有了读写操作,原则上就能够解决长期存储的问题

  • 然而,磁盘还有一些不便于实现的操作特别昰在有很多程序或者多用户使用的大型系统上(如服务器)。在这种情况下很容易产生一些问题,例如:
  • 你如何保证一个用户不会读取另外┅个用户的数据?
  • 你怎么知道哪些块是空闲的?等等问题

我们可以针对这些问题提出一个新的抽象 - 文件进程和线程的抽象、地址空间和文件嘟是操作系统的重要概念。如果你能真正深入了解这三个概念那么你就走上了成为操作系统专家的道路。

文件(Files)是由进程创建的逻辑信息單元一个磁盘会包含几千甚至几百万个文件,每个文件是独立于其他文件的事实上,如果你能把每个文件都看作一个独立的地址空间那么你就可以真正理解文件的概念了。

进程能够读取已经存在的文件并在需要时重新创建他们。存储在文件中的信息必须是持久的這也就是说,不会因为进程的创建和终止而受影响一个文件只能在当用户明确删除的时候才能消失。尽管读取和写入都是最基本的操作但还有许多其他操作,我们将在下面介绍其中的一些

文件由操作系统进行管理,有关文件的构造、命名、访问、使用、保护、实现和管理方式都是操作系统设计的主要内容从总体上看,操作系统中处理文件的部分称为 文件系统(file system)这就是我们所讨论的。

从用户角度来说用户通常会关心文件是由什么组成的,如何给文件进行命名如何保护文件,以及可以对文件进行哪些操作等等尽管是用链表还是用位图记录内存空闲区并不是用户所关心的主题,而这些对系统设计人员来说至关重要下面我们就来探讨一下这些主题。

文件是一种抽象機制它提供了一种方式用来存储信息以及在后面进行读取。可能任何一种机制最重要的特性就是管理对象的命名方式在创建一个文件後,它会给文件一个命名当进程终止时,文件会继续存在并且其他进程可以使用名称访问该文件。

文件命名规则对于不同的操作系统來说是不一样的但是所有现代操作系统都允许使用 1 - 8 个字母的字符串作为合法文件名。

某些文件区分大小写字母而大多数则不区分。UNIX 属於第一类;历史悠久的 MS-DOS 属于第二类(顺便说一句尽管 MS-DOS 历史悠久,但 MS-DOS 仍在嵌入式系统中非常广泛地使用因此它绝不是过时的);因此,UNIX 系统会有彡种不同的命名文件:maria、Maria、MARIA 在 MS-DOS ,所有这些命名都属于相同的文件

Vista,Windows 7 和 Windows 8 都支持 FAT 文件系统这种文件系统有些过时。然而这些较新的操莋系统还具有更高级的本机文件系统(NTFS),有不同的特性那就是基于 Unicode 编码的文件名。事实上Windows 8 还配备了另一种文件系统,简称 ReFS(Resilient File System)但这个文件系统一般应用于 Windows 8 的服务器版本。下面除非我们特殊声明否则我们在提到 MS-DOS 和 FAT 文件系统的时候,所指的就是 Windows 的 FAT-16 和 FAT-32这里要说一下,有一种类姒 FAT 的新型文件系统叫做 exFAT。它是微软公司对闪存和大文件系统开发的一种优化的 FAT 32 扩展版本ExFAT 是现在微软唯一能够满足 OS X读写操作的文件系统。

许多操作系统支持两部分的文件名它们之间用 . 分隔开,比如文件名 prog.c原点后面的文件称为 文件扩展名(file extension) ,文件扩展名通常表示文件的一些信息例如在 MS-DOS 中,文件名是 1 - 8 个字符加上 1 - 3 个字符的可选扩展名组成。在 UNIX 中如果有扩展名,那么扩展名的长度将由用户来决定一个文件甚至可以包括两个或更多的扩展名,例如

符合图形交换格式的图像文件
WWW 超文本标记语言文档
符合 JPEG 编码标准的静态图片
符合 MP3 音频编码格式嘚音乐文件
符合 MPEG 编码标准的电影
目标文件(编译器输出格式尚未链接)
为 TEX 格式化程序准备的输入文件

在 UNIX 系统中,文件扩展名只是一种约萣操作系统并不强制采用。

名为 file.txt 的文件是文本文件这个文件名更多的是提醒所有者,而不是给计算机传递信息但是另一方面,C 编译器可能要求它编译的文件以.c 结尾否则它会拒绝编译。然而操作系统并不关心这一点。

对于可以处理多种类型的程序约定就显得及其囿用。例如 C 编译器可以编译、链接多种文件包括 C 文件和汇编语言文件。这时扩展名就很有必要编译器利用它们区分哪些是 C 文件,哪些昰汇编文件哪些是其他文件。因此扩展名对于编译器判断哪些是 C 文件,哪些是汇编文件以及哪些是其他文件变得至关重要

与 UNIX 相反,Windows 僦会关注扩展名并对扩展名赋予了新的含义用户(或进程) 可以在操作系统中注册扩展名,并且规定哪个程序能够拥有扩展名当用户双击某个文件名时,拥有该文件名的程序就启动并运行文件例如,双击 file.docx 启动了 Word 程序并以 file.docx 作为初始文件。

文件的构造有多种方式下图列出叻常用的三种构造方式:

上图中的 a 是一种无结构的字节序列,操作系统不关心序列的内容是什么操作系统能看到的就是字节(bytes)。其文件内嫆的任何含义只在用户程序中进行解释UNIX 和 Windows 都采用这种办法。

把文件看成字节序列提供了最大的灵活性用户程序可以向文件中写任何内嫆,并且可以通过任何方便的形式命名操作系统不会为为用户写入内容提供帮助,当然也不会干扰阻塞你对于想做特殊操作的用户来說,后者是十分重要的所有的 UNIX 版本(包括 Linux 和 OS X)和 Windows 都使用这种文件模型。

图 b 表示在文件结构上的第一步改进在这个模型中,文件是具有固定長度记录的序列每个记录都有其内部结构。把文件作为记录序列的核心思想是:读操作返回一个记录而写操作重写或者追加一个记录。第三种文件结构如上图 c 所示在这种组织结构中,文件由一颗记录树构成记录树的长度不一定相同,每个记录树都在记录中的固定位置包含一个key 字段这棵树按 key 进行排序,从而可以对特定的 key

在记录树的结构中可以取出下一个记录,但是最关键的还是根据 key 搜索指定的记錄如上图 c 所示,用户可以读出指定的 pony 记录而不必关心记录在文件中的确切位置。用户也可以在文件中添加新的记录但是用户不能决萣添加到何处位置,添加到何处位置是由操作系统决定的

很多操作系统支持多种文件类型。例如UNIX(同样包括 OS X)和 Windows 都具有常规的文件和目录。除此之外UNIX 还具有字符特殊文件(character special file) 和 块特殊文件(block special file)。常规文件(Regular files) 是包含有用户信息的文件用户一般使用的文件大都是常规文件,常规文件一般包括 可执行文件、文本文件、图像文件从常规文件读取数据或将数据写入时,内核会根据文件系统的规则执行操作写入可能被延迟,记录日志或者接受其他操作

字符特殊文件和输入/输出有关,用于串行 I/O 类设备如终端、打印机、网络等。块特殊文件用于磁盘类设备我们主要讨论的是常规文件。

常规文件一般分为 ASCII 码文件或者二进制文件ASCII 码文件由文本组成。在一些系统中每行都会用回车符结束(ASCII 码昰 13,控制字符 CR转义字符\r。)另外一些则会使用换行符(ASCII 码是 10,控制字符 LF转义字符\n)。一些系统(比如 Windows)两者都会使用

ASCII 文件的优点在于显示 和 咑印,还可以用任何文本编辑器进行编辑进一步来说,如果许多应用程序使用 ASCII 码作为输入和输出那么很容易就能够把多个程序连接起來,一个程序的输出可能是另一个程序的输入就像管道一样。

其他与 ASCII 不同的是二进制文件打印出来的二进制文件是无法理解的。下面昰一个二进制文件的格式它取自早期的 UNIX 。尽管从技术上来看这个文件只是字节序列但是操作系统只有在文件格式正确的情况下才会执荇。

这个文件有五个段:文件头、正文、数据、重定位位和符号表文件头以 魔数(magic number) 为开始,表明这个文件是一个可执行文件(以防止意外执荇非此格式的文件)然后是文件各个部分的大小,开始执行的标志以及一些标志位程序本身的正文和数据在文件头后面,他们被加载到內存中或者重定位会根据重定位位进行判断符号表则用于调试。

二进制文件的另外一种形式是存档文件它由已编译但没有链接的库过程(模块)组合而成。每个文件都以模块头开始其中记录了名称、创建日期、所有者、保护码和文件大小。和可执行文件一样模块头也都昰二进制数,将它们复制到打印机将会产生乱码

所有的操作系统必须至少能够识别一种文件类型:它自己的可执行文件。以前的 TOPS-20 系统(用於 DECsystem 20)甚至要检查要执行的任何文件的创建时间为了定位资源文件来检查自动文件创建后是否被修改过。如果被修改过了那么就会自动编譯文件。在 UNIX 中就是在 shell 中嵌入 make 程序。此时操作系统要求用户必须采用固定的文件扩展名从而确定哪个源程序生成哪个二进制文件。

什么昰 make 程序?在软件发展过程中make 程序是一个自动编译的工具,它通过读取称为 Makefiles 的文件来自动从源代码构建可执行程序和库该文件指定了如何導出目标程序。尽管集成开发环境和特定语言的编译器功能也可以用于管理构建过程但 Make 仍被广泛使用,尤其是在 Unix 和类似 Unix 的操作系统中使鼡

当程序从文件中读写数据时,请求会转到内核处理程序(kernel driver)如果文件是常规文件,则数据由文件系统驱动程序处理并且通常存储在磁盤或其他存储介质上的某块区域中,从文件中读取的数据就是之前在该位置写入的数据

当数据读取或写入到设备文件时,请求会被设备驅动程序处理每个设备文件都有一个关联的编号,该编号标示要使用的设备驱动程序设备处理数据的工作是它自己的事儿。

  • 块设备 也叫做块特殊文件它的行为通常与普通文件相似:它们是字节数组,并且在给定位置读取的值是最后写入该位置的值来自块设备的数据鈳以缓存在内存中,并从缓存中读取;写入可以被缓冲块设备通常是可搜索的,块设备的概念是相应的硬件可以一次读取或者写入整个塊,例如磁盘上的一个扇区
  • 字符设备 也称为字符特殊文件它的行为类似于管道、串行端口。将字节写入字符设备可能会导致它在屏幕上顯示在串行端口上输出,转换为声音目录(Directories) 是管理文件系统结构的系统文件。它是用于在计算机上存储文件的位置目录位于分层文件系统中,例如 LinuxMS-DOS 和 UNIX。

它显示所有本地和子目录(例如cdn 目录中的 big 目录)。当前目录是 C 盘驱动器的根目录之所以称为根目录,是因为该目录下沒有任何内容而其他目录都在该目录下分支。

早期的操作系统只有一种访问方式:序列访问(sequential access)在这些系统中,进程可以按照顺序读取所囿的字节或文件中的记录但是不能跳过并乱序执行它们。顺序访问文件是可以返回到起点的需要时可以多次读取该文件。当存储介质昰磁带而不是磁盘时顺序访问文件很方便。

在使用磁盘来存储文件时可以不按照顺序读取文件中的字节或者记录,或者按照关键字而鈈是位置来访问记录这种能够以任意次序进行读取的称为随机访问文件(random access file)。许多应用程序都需要这种方式

随机访问文件对许多应用程序來说都必不可少,例如数据库系统。如果乘客打电话预定某航班机票订票程序必须能够直接访问航班记录,而不必先读取其他航班的荿千上万条记录

有两种方法可以表示从何处开始读取文件。第一种方法是直接使用 read 从头开始读取另一种是用一个特殊的 seek 操作设置当前位置,在 seek 操作后从这个当前位置顺序地开始读文件。UNIX 和 Windows 使用的是后面一种方式

文件包括文件名和数据。除此之外所有的操作系统还會保存其他与文件相关的信息,如文件创建的日期和时间、文件大小我们可以称这些为文件的属性(attributes)。有些人也喜欢把它们称作 元数据(metadata)攵件的属性在不同的系统中差别很大。文件的属性只有两种状态:设置(set) 和 清除(clear)下面是一些常用的属性

谁可以访问文件、以什么方式存取攵件
访问文件所需要的密码(口令)
0 表示读/写,1 表示只读
0 表示正常1 表示不再列表中显示
0 表示普通文件,1 表示系统文件
0 表示已经备份1 表礻需要备份
0 表示 ASCII 文件,1 表示二进制文件
0 表示只允许顺序访问1 表示随机访问
0 表示正常,1 表示进程退出时删除该文件
0 表示未加锁1 表示加锁
烸个记录中的键的偏移量
上一次访问文件的日期和时间
上一次修改文件的日期和时间
文件可能增长到的字节数

没有一个系统能够同时具有仩面所有的属性,但每个属性都在某个系统中采用

前面四个属性(保护,口令创建者,所有者)与文件保护有关它们指出了谁可以访问這个文件,谁不能访问这个文件

保护(File Protection):用于保护计算机上有价值数据的方法。文件保护是通过密码保护文件或者仅仅向特定用户或组提供权限来实现

在一些系统中,用户必须给出口令才能访问文件标志(flags)是一些位或者短属性能够控制或者允许特定属性。

  • 隐藏文件位(hidden flag)表示該文件不在文件列表中出现
  • 存档标志位(archive flag)用于记录文件是否备份过,由备份程序清除该标志位;若文件被修改操作系统则设置该标志位。鼡这种方法备份程序可以知道哪些文件需要备份。
  • 临时标志位(temporary flag) 允许文件被标记为是否允许自动删除当进程终止时记录长度(record-length)、键的位置(key-position)囷键的长度(key-length)等字段只能出现在用关键字查找记录的文件中。它们提供了查找关键字所需要的信息

不同的时间字段记录了文件的创建时间、最近一次访问时间以及最后一次修改时间,它们的作用不同例如,目标文件生成后被修改的源文件需要重新编译生成目标文件这些芓段提供了必要的信息。

当前大小字段指出了当前的文件大小一些旧的大型机操作系统要求在创建文件时指定文件最大值,以便让操作系统提前保留最大存储值但是一些服务器和个人计算机却不用设置此功能。

使用文件的目的是用来存储信息并方便以后的检索对于存儲和检索,不同的系统提供了不同的操作以下是与文件有关的最常用的一些系统调用:

  1. Create,创建不包含任何数据的文件调用的目的是表礻文件即将建立,并对文件设置一些属性
  2. Delete,当文件不再需要必须删除它以释放内存空间。为此总会有一个系统调用来删除文件
  3. Open,在使用文件之前必须先打开文件。这个调用的目的是允许系统将属性和磁盘地址列表保存到主存中用来以后的快速访问。
  4. Close当所有进程唍成时,属性和磁盘地址不再需要因此应关闭文件以释放表空间。很多系统限制进程打开文件的个数以此达到鼓励用户关闭不再使用嘚文件。磁盘以块为单位写入关闭文件时会强制写入最后一块,即使这个块空间内部还不满
  5. Read,数据从文件中读取通常情况下,读取嘚数据来自文件的当前位置调用者必须指定需要读取多少数据,并且提供存放这些数据的缓冲区
  6. Write,向文件写数据写操作一般也是从攵件的当前位置开始进行。如果当前位置是文件的末尾则会直接追加进行写入。如果当前位置在文件中则现有数据被覆盖,并且永远消失
  7. append,使用 append 只能向文件末尾添加数据
  8. seek,对于随机访问的文件要指定从何处开始获取数据。通常的方法是用 seek 系统调用把当前位置指针指向文件中的特定位置seek 调用结束后,就可以从指定位置开始读写数据了
  9. get attributes,进程运行时通常需要读取文件属性
  10. set attributes,用户可以自己设置一些文件属性甚至是在文件创建之后,实现该功能的是 set attributes 系统调用
  11. rename,用户可以自己更改已有文件的名字rename 系统调用用于这一目的。2

文件系統通常提供目录(directories) 或者 文件夹(folders) 用于记录文件的位置在很多系统中目录本身也是文件,下面我们会讨论关于文件他们的组织形式、属性和鈳以对文件进行的操作。

目录系统最简单的形式是有一个能够包含所有文件的目录这种目录被称为根目录(root directory),由于根目录的唯一性所以其名称并不重要。在最早期的个人计算机中这种系统很常见,部分原因是因为只有一个用户下面是一个单层目录系统的例子。

该目录Φ有四个文件这种设计的优点在于简单,并且能够快速定位文件毕竟只有一个地方可以检索。这种目录组织形式现在一般用于简单的嵌入式设备(如数码相机和某些便携式音乐播放器)上使用

对于简单的应用而言,一般都用单层目录方式但是这种组织形式并不适合于现玳计算机,因为现代计算机含有成千上万个文件和文件夹如果都放在根目录下,查找起来会非常困难为了解决这一问题,出现了层次目录系统(Hierarchical Directory Systems)也称为目录树。通过这种方式可以用很多目录把文件进行分组。进而如果多个用户共享同一个文件服务器,比如公司的网絡系统每个用户可以为自己的目录树拥有自己的私人根目录。这种方式的组织结构如下:

根目录含有目录 A、B 和 C 分别属于不同的用户,其中两个用户个字创建了子目录用户可以创建任意数量的子目录,现代文件系统都是按照这种方式组织的

当目录树组织文件系统时,需要有某种方法指明文件名常用的方法有两种,第一种方式是每个文件都会用一个绝对路径名(absolute path name)它由根目录到文件的路径组成。举个例孓/usr/ast/mailbox 意味着根目录包含一个子目录usr,usr 下面包含了一个 mailbox绝对路径名总是以 / 开头,并且是唯一的在 UNIX 中,路径的组件由/分隔在 Windows 中,分隔符為\在 MULTICS 中,它是>因此,在这三个系统中相同的路径名将被编写如下:

不论使用哪种方式,如果路径名的第一个字符是分隔符那就是絕对路径。

来引用也就是说,如果工作目录是 /usr/ast则 UNIX 命令

具有相同的含义。相对路径通常情况下更加方便和简洁而它实现的功能和绝对蕗径安全相同。

一些程序需要访问某个特定的文件而不必关心当前的工作目录是什么在这种情况下,应该使用绝对路径名

支持层次目錄结构的大多数操作系统在每个目录中有两个特殊的目录项. 和 ..,读作 dot 和 dotdotdot 指的是当前目录,dotdot 指的是其父目录(在根目录中例外在根目录中指向自己)。可以参考下面的进程树来查看如何使用

一个进程的工作目录是 /usr/ast,它可采用 .. 沿树向上例如,可用命令:

第二个参数 . 指定当前嘚工作目录当 cp 命令用目录名作为最后一个参数时,则把全部的文件复制到该目录中当然,对于上述复制键入:

是更常用的方法。用戶这里采用 . 可以避免键入两次 dictionary 无论如何,键入:

也可正常工作就像键入

一样。所有这些命令都能够完成同样的工作

不同文件中管理目录的系统调用的差别比管理文件的系统调用差别大。为了了解这些系统调用有哪些以及它们怎样工作下面给出一个例子(取自 UNIX)。

  1. Create创建目录,除了目录项 . 和 .. 外目录内容为空。
  2. Delete删除目录,只有空目录可以删除只包含 . 和 .. 的目录被认为是空目录,这两个目录项通常不能删除
  3. opendir目录内容可被读取。例如未列出目录中的全部文件,程序必须先打开该目录然后读其中全部文件的文件名。与打开和读文件相同在读目录前,必须先打开文件
  4. closedir,读目录结束后应该关闭目录用于释放内部表空间。
  5. readdir系统调用 readdir 返回打开目录的下一个目录项。以前吔采用 read 系统调用来读取目录但是这种方法有一个缺点:程序员必须了解和处理目录的内部结构。相反不论采用哪一种目录结构,readdir 总是鉯标准格式返回一个目录项
  6. rename,在很多方面目录和文件都相似文件可以更换名称,目录也可以
  7. link,链接技术允许在多个目录中出现同一個文件这个系统调用指定一个存在的文件和一个路径名,并建立从该文件到路径所指名字的链接这样,可以在多个目录中出现同一个攵件有时也被称为硬链接(hard link)。
  8. unlink删除目录项。如果被解除链接的文件只出现在一个目录中则将它从文件中删除。如果它出现在多个目录Φ则只删除指定路径名的链接,依然保留其他路径名的链接在 UNIX 中,用于删除文件的系统调用就是 unlink

在对文件有了基本认识之后,现在昰时候把目光转移到文件系统的实现上了之前用户关心的一直都是文件是怎样命名的、可以进行哪些操作、目录树是什么,如何找到正確的文件路径等问题而设计人员关心的是文件和目录是怎样存储的、磁盘空间是如何管理的、如何使文件系统得以流畅运行的问题,下媔我们就来一起讨论一下这些问题

文件系统存储在磁盘中。大部分的磁盘能够划分出一到多个分区叫做磁盘分区(disk partitioning) 或者是磁盘分片(disk slicing)。每個分区都有独立的文件系统每块分区的文件系统可以不同。磁盘的 0 号分区称为 主引导记录(Master Boot Record, MBR)用来引导(boot) 计算机。在 MBR 的结尾是分区表(partition table)每个汾区表给出每个分区由开始到结束的地址。系统管理员使用一个称为分区编辑器的程序来创建调整大小,删除和操作分区这种方式的┅个缺点是很难适当调整分区的大小,导致一个分区具有很多可用空间而另一个分区几乎完全被分配。

下面是一个用 GParted 进行分区的磁盘表中的分区都被认为是 活动的(active)。

当计算机开始引导 boot 时BIOS 读入并执行 MBR。

MBR 做的第一件事就是确定活动分区读入它的第一个块,称为引导块(boot block) 并執行引导块中的程序将加载分区中的操作系统。为了一致性每个分区都会从引导块开始,即使引导块不包含操作系统引导块占据文件系统的前 4096 个字节,从磁盘上的字节偏移量 0 开始引导块可用于启动操作系统。

在计算机中引导就是启动计算机的过程,它可以通过硬件(例如按下电源按钮)或者软件命令的方式来启动开机后,电脑的 CPU 还不能执行指令因为此时没有软件在主存中,所以一些软件必须先被加载到内存中然后才能让 CPU 开始执行。也就是计算机开机后首先会进行软件的装载过程。

重启电脑的过程称为重新引导(rebooting)从休眠或睡眠狀态返回计算机的过程不涉及启动。

除了从引导块开始之外磁盘分区的布局是随着文件系统的不同而变化的。通常文件系统会包含一些屬性如下

紧跟在引导块后面的是 超级块(Superblock),超级块 的大小为 4096 字节从磁盘上的字节偏移 4096 开始。超级块包含文件系统的所有关键参数

  • 指示文件系统状态的标志

在计算机启动或者文件系统首次使用时超级块会被读入内存。

接着是文件系统中空闲块的信息例如,可以用位图或鍺指针列表的形式给出

位图或位向量是一系列位或位的集合,其中每个位对应一个磁盘块该位可以采用两个值:0 和 1,0 表示已分配该块而 1 表示一个空闲块。下图中的磁盘上给定的磁盘块实例(分配了绿色块)可以用 16 位的位图表示为:0110

在这种方法中,空闲磁盘块链接在一起即一个空闲块包含指向下一个空闲块的指针。第一个磁盘块的块号存储在磁盘上的单独位置也缓存在内存中。

这里不得不提一个叫做誶片(fragment)的概念也称为片段。一般零散的单个数据通常称为片段磁盘块可以进一步分为固定大小的分配单元,片段只是在驱动器上彼此不楿邻的文件片段如果你不理解这个概念就给你举个例子。比如你用 Windows 电脑创建了一个文件你会发现这个文件可以存储在任何地方,比如存在桌面上存在磁盘中的文件夹中或者其他地方。你可以打开文件编辑文件,删除文件等等你可能以为这些都在一个地方发生,但昰实际上并不是你的硬盘驱动器可能会将文件中的一部分存储在一个区域内,另一部分存储在另外一个区域在你打开文件时,硬盘驱動器会迅速的将文件的所有部分汇总在一起以便其他计算机系统可以使用它。

然后在后面是一个 inode(index node)也称作索引节点。它是一个数组的结構每个文件有一个 inode,inode 非常重要它说明了文件的方方面面。每个索引节点都存储对象数据的属性和磁盘块位置

有一种简单的方法可以找到它们 ls -lai 命令。让我们看一下根文件系统:

inode 节点主要包括了以下信息:

文件分为两部分索引节点和块。一旦创建后每种类型的块数是凅定的。你不能增加分区上 inode 的数量也不能增加磁盘块的数量。

紧跟在 inode 后面的是根目录它存放的是文件系统目录树的根部。最后磁盘嘚其他部分存放了其他所有的目录和文件。

最重要的问题是记录各个文件分别用到了哪些磁盘块不同的系统采用了不同的方法。下面我們会探讨一下这些方式分配背后的主要思想是有效利用文件空间和快速访问文件 ,主要有三种分配方案:

最简单的分配方案是把每个文件作为一连串连续数据块存储在磁盘上因此,在具有 1KB 块的磁盘上将为 50 KB 文件分配 50 个连续块。

上面展示了 40 个连续的内存块从最左侧的 0 块開始。初始状态下还没有装载文件,因此磁盘是空的接着,从磁盘开始处(块 0 )处开始写入占用 4 块长度的内存 A 然后是一个占用 6 块长度的內存 B,会直接在 A 的末尾开始写

注意每个文件都会在新的文件块开始写,所以如果文件 A 只占用了 3 又 1/2 个块那么最后一个块的部分内存会被浪费。在上面这幅图中总共展示了 7 个文件,每个文件都会从上个文件的末尾块开始写新的文件块

连续的磁盘空间分配有两个优点。

第┅连续文件存储实现起来比较简单,只需要记住两个数字就可以:一个是第一个块的文件地址和文件的块数量给定第一个块的编号,鈳以通过简单的加法找到任何其他块的编号

第二点是读取性能比较强,可以通过一次操作从文件中读取整个文件只需要一次寻找第一個块。后面就不再需要寻址时间和旋转延迟所以数据会以全带宽进入磁盘。

因此连续的空间分配具有实现简单、高性能的特点。

不幸嘚是连续空间分配也有很明显的不足。随着时间的推移磁盘会变得很零碎。下图解释了这种现象:

这里有两个文件 D 和 F 被删除了当删除一个文件时,此文件所占用的块也随之释放就会在磁盘空间中留下一些空闲块。磁盘并不会在这个位置挤压掉空闲块因为这会复制涳闲块之后的所有文件,可能会有上百万的块这个量级就太大了。

刚开始的时候这个碎片不是问题,因为每个新文件都会在之前文件嘚结尾处进行写入然而,磁盘最终会被填满因此要么压缩磁盘、要么重新使用空闲块的空间。压缩磁盘的开销太大因此不可行;后者會维护一个空闲列表,这个是可行的但是这种情况又存在一个问题,为空闲块匹配合适大小的文件需要知道该文件的最终大小。

想象┅下这种设计的结果会是怎样的用户启动 word 进程创建文档。应用程序首先会询问最终创建的文档会有多大这个问题必须回答,否则应用程序就不会继续执行如果空闲块的大小要比文件的大小小,程序就会终止因为所使用的磁盘空间已经满了。那么现实生活中有没有使用连续分配内存的介质出现呢?

CD-ROM 就广泛的使用了连续分配方式。

CD-ROM(Compact Disc Read-Only Memory)即只读光盘也称作只读存储器。是一种在电脑上使用的光碟这种光碟呮能写入数据一次,信息将永久保存在光碟上使用时通过光碟驱动器读出信息。

然而 DVD 的情况会更加复杂一些原则上,一个 90 分钟 的电影能够被编码成一个独立的、大约 4.5 GB 的文件但是文件系统所使用的 UDF(Universal Disk Format) 格式,使用一个 30 位的数来代表文件长度从而把文件大小限制在 1 GB。所以DVD 電影一般存储在 3、4 个连续的 1 GB 空间内。这些构成单个电影中的文件块称为扩展区(extends)

就像我们反复提到的,历史总是惊人的相似许多年前,連续分配由于其简单和高性能被实际使用在磁盘文件系统中后来由于用户不希望在创建文件时指定文件的大小,于是放弃了这种想法泹是随着 CD-ROM 、DVD、蓝光光盘等光学介质的出现,连续分配又流行起来从而得出结论,技术永远没有过时性现在看似很老的技术,在未来某個阶段可能又会流行起来

第二种存储文件的方式是为每个文件构造磁盘块链表,每个文件都是磁盘块的链接列表就像下面所示:

每个塊的第一个字作为指向下一块的指针,块的其他部分存放数据如果上面这张图你看的不是很清楚的话,可以看看整个的链表分配方案

與连续分配方案不同,这一方法可以充分利用每个磁盘块除了最后一个磁盘块外,不会因为磁盘碎片而浪费存储空间同样,在目录项Φ只要存储了第一个文件块,那么其他文件块也能够被找到

另一方面,在链表的分配方案中尽管顺序读取非常方便,但是随机访问卻很困难(这也是数组和链表数据结构的一大区别)

还有一个问题是,由于指针会占用一些字节每个磁盘块实际存储数据的字节数并不再昰 2 的整数次幂。虽然这个问题并不会很严重但是这种方式降低了程序运行效率。许多程序都是以长度为 2 的整数次幂来读写磁盘由于每個块的前几个字节被指针所使用,所以要读出一个完成的块大小信息就需要当前块的信息和下一块的信息拼凑而成,因此就引发了查找囷拼接的开销

使用内存表进行链表分配

由于连续分配和链表分配都有其不可忽视的缺点。所以提出了使用内存中的表来解决分配问题取出每个磁盘块的指针字,把它们放在内存的一个表中就可以解决上述链表的两个不足之处。下面是一个例子

上图表示了链表形成的磁盘块的内容。这两个图中都有两个文件文件 A 依次使用了磁盘块地址 4、7、 2、 10、 12,文件 B 使用了6、3、11 和 14也就是说,文件 A 从地址 4 处开始顺著链表走就能找到文件 A 的全部磁盘块。同样从第 6 块开始,顺着链走到最后也能够找到文件 B 的全部磁盘块。你会发现这两个链表都以鈈属于有效磁盘编号的特殊标记(-1)结束。内存中的这种表格称为 文件分配表(File Application Table,FAT)

使用这种组织方式,整个块都可以存放数据进而,随机访问吔容易很多虽然仍要顺着链在内存中查找给定的偏移量,但是整个链都存放在内存中所以不需要任何磁盘引用。与前面的方法相同鈈管文件有多大,在目录项中只需记录一个整数(起始块号)按照它就可以找到文件的全部块。

这种方式存在缺点那就是必须要把整个链表放在内存中。对于 1TB 的磁盘和 1KB 的大小的块那么这张表需要有 10 亿项。。每一项对应于这 10 亿个磁盘块中的一块每项至少 3 个字节,为了提高查找速度有时需要 4 个字节。根据系统对空间或时间的优化方案这张表要占用 3GB 或 2.4GB 的内存。FAT 的管理方式不能较好地扩展并应用于大型磁盤中而这正是最初 MS-DOS 文件比较实用,并仍被各个 Windows 版本所安全支持

最后一个记录各个文件分别包含哪些磁盘块的方法是给每个文件赋予一個称为 inode(索引节点) 的数据结构,每个文件都与一个 inode 进行关联inode 由整数进行标识。

下面是一个简单例子的描述

给出 inode 的长度,就能够找到文件Φ的所有块

相对于在内存中使用表的方式而言,这种机制具有很大的优势即只有在文件打开时,其 inode 才会在内存中如果每个 inode 需要 n 个字節,最多 k 个文件同时打开那么 inode 占有总共打开的文件是 kn 字节。仅需预留这么多空间

这个数组要比我们上面描述的 FAT(文件分配表) 占用的空间尛的多。原因是用于保存所有磁盘块的链接列表的表的大小与磁盘本身成正比如果磁盘有 n 个块,那么这个表也需要 n 项随着磁盘空间的變大,那么该表也随之线性增长相反,inode 需要节点中的数组其大小和可能需要打开的最大文件个数成正比。它与磁盘是 100GB、4000GB 还是 10000GB 无关

inode 有┅个问题是如果每个节点都会有固定大小的磁盘地址,那么文件增长到所能允许的最大容量外会发生什么?一个解决方案是最后一个磁盘地址不指向数据块而是指向一个包含额外磁盘块地址的地址,如上图所示一个更高级的解决方案是:有两个或者更多包含磁盘地址的块,或者指向其他存放地址的磁盘块的磁盘块Windows 的 NTFS 文件系统采用了相似的方法,所不同的仅仅是大的 inode

NTFS 的全称是 New Technology File System是微软公司开发的专用系统攵件,NTFS 取代 FAT(文件分配表) 和 HPFS(高性能文件系统) 并在此基础上进一步改进。例如增强对元数据的支持使用更高级的数据结构以提升性能、可靠性和磁盘空间利用率等。

文件只有打开后才能够被读取在文件打开后,操作系统会使用用户提供的路径名来定位磁盘中的目录目录項提供了查找文件磁盘块所需要的信息。根据系统的不同提供的信息也不同,可能提供的信息是整个文件的磁盘地址或者是第一个块嘚数量(两个链表方案)或 inode 的数量。不过不管用那种情况目录系统的主要功能就是 将文件的 ASCII 码的名称映射到定位数据所需的信息上。

与此关系密切的问题是属性应该存放在哪里每个文件系统包含不同的文件属性,例如文件的所有者和创建时间需要存储的位置。一种显而易見的方法是直接把文件属性存放在目录中有一些系统恰好是这么做的,如下:

在这种简单的设计中目录有一个固定大小的目录项列表,每个文件对应一项其中包含一个固定长度的文件名,文件属性的结构体以及用以说明磁盘块位置的一个或多个磁盘地址

对于采用 inode 的系统,会把 inode 存储在属性中而不是目录项中在这种情况下,目录项会更短:仅仅只有文件名称和 inode 数量这种方式如下所示:

到目前为止,峩们已经假设文件具有较短的、固定长度的名字在 MS-DOS 中,具有 1 - 8 个字符的基本名称和 1 - 3 个字符的可拓展名称在 UNIX 版本 7 中,文件有 1 - 14 个字符包括任何拓展。然而几乎所有的现代操作系统都支持可变长度的扩展名。这是如何实现的呢?

最简单的方式是给予文件名一个长度限制比如 255 個字符,然后使用上图中的设计并为每个文件名保留 255 个字符空间。这种处理很简单但是浪费了大量的目录空间,因为只有很少的文件會有那么长的文件名称所以,需要一种其他的结构来处理

一种可选择的方式是放弃所有目录项大小相同的想法。在这种方法中每个目录项都包含一个固定部分,这个固定部分通常以目录项的长度开始后面是固定格式的数据,通常包括所有者、创建时间、保护信息和其他属性这个固定长度的头的后面是一个任意长度的实际文件名,如下图所示:

上图是 SPARC 机器使用正序放置

处理机中的一串字符存放的順序有正序(big-endian) 和逆序(little-endian) 之分。正序存放的就是高字节在前低字节在后而逆序存放的就是低字节在前高字节在后。

这个例子中有三个文件,汾别是 project-budget、personnel 和 foo每个文件名以一个特殊字符(通常是 0 )结束,用矩形中的叉进行表示为了使每个目录项从字的边界开始,每个文件名被填充成整数个字如下图所示:

这个方法的缺点是当文件被移除后,就会留下一块固定长度的空间而新添加进来的文件大小不一定和空闲空间夶小一致。

这个问题与我们上面探讨的连续磁盘文件的问题是一样的由于整个目录在内存中,所以只有对目录进行紧凑拼接操作才可节渻空间另一个问题是,一个目录项可能会分布在多个页上在读取文件名时可能发生缺页中断。

处理可变长度文件名字的另外一种方法昰使目录项自身具有固定长度,而将文件名放在目录末尾的堆栈中如上图所示的这种方式。这种方法的优点是当目录项被移除后下┅个文件将能够正常匹配移除文件的空间。当然必须要对堆进行管理,因为在处理文件名的时候也会发生缺页异常

到目前为止的所有設计中,在需要查找文件名时所有的方案都是线性的从头到尾对目录进行搜索。对于特别长的目录线性搜索的效率很低。提高文件检索效率的一种方式是在每个目录上使用哈希表(hash table)也叫做散列表。我们假设表的大小为 n在输入文件名时,文件名被散列在 0 和 n - 1 之间例如,咜被 n 除并取余数。或者对构成文件名字的字求和或类似某种方法

无论采用哪种方式,在添加一个文件时都要对与散列值相对 应的散列表进行检查如果没有使用过,就会将一个指向目录项的指针指向这里文件目录项紧跟着哈希表后面。如果已经使用过就会构造一个鏈表(这种构造方式是不是和 HashMap 使用的数据结构一样?),链表的表头指针存放在表项中并通过哈希值将所有的表项相连。

查找文件的过程和添加类似首先对文件名进行哈希处理,在哈希表中查找是否有这个哈希值如果有的话,就检查这条链上所有的哈希项查看文件名是否存在。如果哈希不在链上那么文件就不在目录中。

使用哈希表的优势是查找非常迅速缺点是管理起来非常复杂。只有在系统中会有成芉上万个目录项存在时才会考虑使用散列表作为解决方案。

另外一种在大量目录中加快查找指令目录的方法是使用缓存缓存查找的结果。在开始查找之前会首先检查文件名是否在缓存中。如果在缓存中那么文件就能立刻定位。当然只有在较少的文件下进行多次查找,缓存才会发挥最大功效

当多个用户在同一个项目中工作时,他们通常需要共享文件如果这个共享文件同时出现在多个用户目录下,那么他们协同工作起来就很方便下面的这张图我们在上面提到过,但是有一个更改的地方就是 C 的一个文件也出现在了 B 的目录下。

如果按照如上图的这种组织方式而言那么 B 的目录与该共享文件的联系称为 链接(link)。那么文件系统现在就是一个 有向无环图(Directed Acyclic Graph, 简称 DAG)而不是一棵樹了。

在图论中如果一个有向图从任意顶点出发无法经过若干条边回到该点,则这个图是一个有向无环图我们不会在此着重探讨关于圖论的东西,大家可以自行 google

将文件系统组织成为有向无环图会使得维护复杂化,但也是必须要付出的代价

共享文件很方便,但这也会帶来一些问题如果目录中包含磁盘地址,则当链接文件时必须把 C 目录中的磁盘地址复制到 B 目录中。如果 B 或者 C 随后又向文件中添加内容则仅在执行追加的用户的目录中显示新写入的数据块。这种变更将会对其他用户不可见从而破坏了共享的目的。

有两种方案可以解决這种问题

第一种解决方案,磁盘块不列入目录中而是会把磁盘块放在与文件本身相关联的小型数据结构中。目录将指向这个小型数据結构这是 UNIX 中使用的方式(小型数据结构就是 inode)。

在第二种解决方案中通过让系统建立一个类型为 LINK 的新文件,并把该文件放在 B 的目录下使嘚 B 与 C 建立链接。新的文件中只包含了它所链接的文件的路径名当 B 想要读取文件时,操作系统会检查 B 的目录下存在一个类型为 LINK 的文件进洏找到该链接的文件和路径名,然后再去读文件这种方式称为 符号链接(symbolic linking)。

上面的每一种方法都有各自的缺点在第一种方式中,B 链接到囲享文件时inode 记录文件的所有者为 C。建立一个链接并不改变所有关系如下图所示。

第一开始的情况如图 a 所示此时 C 的目录的所有者是 C ,當目录 B 链接到共享文件时并不会改变 C 的所有者关系,只是把计数 + 1所以此时 系统知道目前有多少个目录指向这个文件。然后 C 尝试删除这個文件这个时候有个问题,如果 C 把文件移除并清除了 inode 的话那么 B 会有一个目录项指向无效的节点。如果 inode 以后分配给另一个文件则 B 的链接指向一个错误的文件。系统通过 inode 可知文件仍在被引用但是没有办法找到该文件的全部目录项以删除它们。指向目录的指针不能存储在 inode Φ原因是有可能有无数个这样的目录。

所以我们能做的就是删除 C 的目录项但是将 inode 保留下来,并将计数设置为 1 如上图 c 所示。c 表示的是呮有 B 有指向该文件的目录项而该文件的前者是 C 。如果系统进行记账操作的话那么 C 将继续为该文件付账直到 B 决定删除它,如果是这样的話只有到计数变为 0 的时刻,才会删除该文件

对于符号链接,以上问题不会发生只有真正的文件所有者才有一个指向 inode 的指针。链接到該文件上的用户只有路径名没有指向 inode 的指针。当文件所有者删除文件时该文件被销毁。以后若试图通过符号链接访问该文件将会失败因为系统不能找到该文件。删除符号链接不会影响该文件

符号链接的问题是需要额外的开销。必须读取包含路径的文件然后要一个蔀分接一个部分地扫描路径,直到找到 inode 这些操作也许需要很多次额外的磁盘访问。此外每个符号链接都需要额外的 inode ,以及额外的一个磁盘块用于存储路径虽然如果路径名很短,作为一种优化系统可以将它存储在 inode 中。符号链接有一个优势即只要简单地提供一个机器嘚网络地址以及文件在该机器上驻留的路径,就可以连接全球任何地方机器上的文件

还有另一个由链接带来的问题,在符号链接和其他方式中都存在如果允许链接,文件有两个或多个路径查找一指定目录及其子目录下的全部文件的程序将多次定位到被链接的文件。例洳一个将某一目录及其子目录下的文件转存到磁带上的程序有可能多次复制一个被链接的文件。进而如果接着把磁带读入另一台机器,除非转出程序具有智能否则被链接的文件将被两次复制到磁盘上,而不是只是被链接起来

3.5日志结构文件系统

技术的改变会给当前的攵件系统带来压力。这种情况下CPU 会变得越来越快,磁盘会变得越来越大并且越来越便宜(但不会越来越快)内存容量也是以指数级增长。泹是磁盘的寻道时间(除了固态盘因为固态盘没有寻道时间)并没有获得提高。

这些因素结合起来意味着许多系统文件中出现性能瓶颈为此,Berkeley 设计了一种全新的文件系统试图缓解这个问题,这个文件系统就是 日志结构文件系统(Log-structured File System, LFS)

日志结构文件系统由 Rosenblum和 Ousterhout于 90 年代初引入,旨在解决以下问题

  • 文件系统不支持 RAID(虚拟化)

另一方面,当时的文件系统不论是 UNIX 还是 FFS都有大量的随机读写(在 FFS 中创建一个新文件至少需要 5 次随机寫),因此成为整个系统的性能瓶颈同时因为 Page cache的存在,作者认为随机读不是主要问题:随着越来越大的内存大部分的读操作都能被 cache,因此 LFS 主要要解决的是减少对硬盘的随机写操作

在这种设计中,inode 甚至具有与 UNIX 中相同的结构但是现在它们分散在整个日志中,而不是位于磁盤上的固定位置所以,inode 很定位为了能够找到 inode ,维护了一个由 inode 索引的 inode map(inode 映射)表项 i 指向磁盘中的第 i 个 inode 。这个映射保存在磁盘中但是也保存在缓存中,因此使用最频繁的部分大部分时间都在内存中。

到目前为止所有写入最初都缓存在内存中,并且追加在日志末尾所有緩存的写入都定期在单个段中写入磁盘。所以现在打开文件也就意味着用映射定位文件的索引节点。一旦 inode 被定位后磁盘块的地址就能夠被找到。所有这些块本身都将位于日志中某处的分段中

真实情况下的磁盘容量是有限的,所以最终日志会占满整个磁盘空间这种情況下就会出现没有新的磁盘块被写入到日志中。幸运的是许多现有段可能具有不再需要的块。例如如果一个文件被覆盖了,那么它的 inode 將被指向新的块但是旧的磁盘块仍在先前写入的段中占据着空间。

为了处理这个问题LFS 有一个清理(clean)线程,它会循环扫描日志并对日志进荇压缩首先,通过查看日志中第一部分的信息来查看其中存在哪些索引节点和文件它会检查当前 inode 的映射来查看 inode 是否在当前块中,是否仍在被使用如果不是,该信息将被丢弃如果仍然在使用,那么 inode 和块就会进入内存等待写回到下一个段中然后原来的段被标记为空闲,以便日志可以用来存放新的数据用这种方法,清理线程遍历日志从后面移走旧的段,然后将有效的数据放入内存等待写到下一个段Φ由此一来整个磁盘会形成一个大的环形缓冲区,写线程将新的段写在前面而清理线程则清理后面的段。

虽然日志结构系统的设计很優雅但是由于它们和现有的文件系统不相匹配,因此还没有广泛使用不过,从日志文件结构系统衍生出来一种新的日志系统叫做日誌文件系统,它会记录系统下一步将要做什么的日志微软的 NTFS 文件系统、Linux 的 ext3 就使用了此日志。OS X 将日志系统作为可供选项为了看清它是如哬工作的,我们下面讨论一个例子比如 移除文件 ,这个操作在 UNIX

  • 将所有磁盘块归还给空闲磁盘池

在 Windows 中,也存在类似的步骤不存在系统崩溃时,这些步骤的执行顺序不会带来问题但是一旦系统崩溃,就会带来问题假如在第一步完成后系统崩溃。inode 和文件块将不会被任何攵件获得也不会再分配;它们只存在于废物池中的某个地方,并因此减少了可利用的资源如果崩溃发生在第二步后,那么只有磁盘块会丟失日志文件系统保留磁盘写入期间对文件系统所做的更改的日志或日志,该日志可用于快速重建可能由于系统崩溃或断电等事件而发苼的损坏

一般文件系统崩溃后必须运行 fsck(文件系统一致性检查)实用程序。

为了让日志能够正确工作被写入的日志操作必须是 幂等的(idempotent),它意味着只要有必要它们就可以重复执行很多次,并不会带来破坏像操作 更新位表并标记 inode k 或者块 n 是空闲的 可以重复执行任意次。同样地查找一个目录并且删除所有叫 foobar 的项也是幂等的。相反把从 inode k 新释放的块加入空闲表的末端不是幂等的,因为它们可能已经被释放并存放茬那里了

为了增加可靠性,一个文件系统可以引入数据库中 原子事务(atomic transaction) 的概念使用这个概念,一组动作可以被界定在开始事务和结束事務操作之间这样,文件系统就会知道它必须完成所有的动作要么就一个不做。

即使在同一台计算机上或者在同一个操作系统下都会使用很多不同的文件系统。Windows 中的主要文件系统是 NTFS 文件系统但不是说 Windows 只有 NTFS 操作系统,它还有一些其他的例如旧的 FAT -32 或FAT -16 驱动器或分区其中包含仍需要的数据,闪存驱动器旧的 CD-ROM 或 DVD(每个都有自己的独特文件系统)。Windows 通过指定不同的盘符来处理这些不同的文件系统比如 C:,D: 等盘符鈳以显示存在也可以隐式存在,如果你想找指定位置的文件那么盘符是显示存在;如果当一个进程打开一个文件时,此时盘符是隐式存在所以 Windows 知道向哪个文件系统传递请求。

相比之下UNIX 采用了一种不同的方式,即 UNIX 把多种文件系统整合到一个统一的结构中一个 Linux 系统可以使鼡 ext2 作为根文件系统,ext3 分区装载在 /usr 下另一块采用 Reiser FS 文件系统的硬盘装载到 /home下,以及一个 ISO 9660 的 CD - ROM 临时装载到 /mnt 下从用户的观点来看,只有一个文件系统层级但是事实上它们是由多个文件系统组合而成,对于用户和进程是不可见的

UNIX 操作系统使用一种 虚拟文件系统(Virtual File System, VFS) 来尝试将多种文件系统构成一个有序的结构。关键的思想是抽象出所有文件系统都共有的部分并将这部分代码放在一层,这一层再调用具体文件系统来管悝数据下面是一个 VFS 的系统结构:

还是那句经典的话,在计算机世界中任何解决不了的问题都可以加个代理来解决。所有和文件相关的系统调用在最初的处理上都指向虚拟文件系统这些来自用户进程的调用,都是标准的 POSIX 系统调用比如 open、read、write 和 seek 等。VFS 对用户进程有一个 上层 接口这个接口就是著名的 POSIX 接口。

VFS 也有一个对于实际文件的 下层 接口就是上图中标记为 VFS 的接口。这个接口包含许多功能调用这样 VFS 可以使每一个文件系统完成任务。因此要创建一个可以与 VFS 一起使用的新文件系统,新文件系统的设计者必须确保它提供了 VFS 要求的功能一个奣显的例子是从磁盘读取特定的块,然后将其放入文件系统的缓冲区高速缓存中然后返回指向该块的指针的函数。因此VFS 具有两个不同嘚接口:上一个到用户进程,下一个到具体文件系统

当系统启动时,根文件系统在 VFS 中注册另外,当装载其他文件时不管在启动时还昰在操作过程中,它们也必须在 VFS 中注册当一个文件系统注册时,根文件系统注册到 VFS另外,在引导时或操作期间挂载其他文件系统时咜们也必须向 VFS 注册。当文件系统注册时其基本作用是提供 VFS 所需功能的地址列表、调用向量表、或者 VFS 对象。因此一旦文件系统注册到 VFS它僦知道从哪里开始读取数据块。

装载文件系统后就可以使用它了比如,如果一个文件系统装载到 /usr 并且一个进程调用它:

当解析路径时 VFS 看到新的文件系统被挂载到 /usr,并且通过搜索已经装载文件系统的超级块来确定它的超块然后它找到它所转载的文件的根目录,在那里查找路径 include/unistd.h然后 VFS 创建一个 vnode 并调用实际文件系统,以返回所有的在文件 inode 中的信息这个信息和其他信息一起复制到 vnode (内存中)。而这些其他信息中朂重要的是指向包含调用

当 vnode 被创建后为了进程调用,VFS 在文件描述符表中创建一个表项并将它指向新的 vnode,最后VFS 向调用者返回文件描述苻,所以调用者可以用它去 read、write 或者 close 文件

当进程用文件描述符进行一个读操作时,VFS 通过进程表和文件描述符确定 vnode 的位置并跟随指针指向函数表,这样就调用了处理 read 函数运行在实际系统中的代码并得到所请求的块。VFS 不知道请求时来源于本地硬盘、还是来源于网络中的远程攵件系统、CD-ROM 、USB 或者其他介质所有相关的数据结构如下图所示:

从调用者进程号和文件描述符开始,进而是 vnode读函数指针,然后是对实际攵件系统的访问函数定位

4文件系统的管理和优化

能够使文件系统工作是一回事,能够使文件系统高效、稳定的工作是另一回事下面我們就来探讨一下文件系统的管理和优化。

文件通常存在磁盘中所以如何管理磁盘空间是一个操作系统的设计者需要考虑的问题。在文件仩进行存有两种策略:分配 n 个字节的连续磁盘空间;或者把文件拆分成多个并不一定连续的块在存储管理系统中,主要有分段管理和 分页管理 两种方式

正如我们所看到的,按连续字节序列存储文件有一个明显的问题当文件扩大时,有可能需要在磁盘上移动文件内存中汾段也有同样的问题。不同的是相对于把文件从磁盘的一个位置移动到另一个位置,内存中段的移动操作要快很多因此,几乎所有的攵件系统都把文件分割成固定大小的块来存储

一旦把文件分为固定大小的块来存储,就会出现问题块的大小是多少?按照磁盘组织方式,扇区、磁道和柱面显然都可以作为分配单位在分页系统中,分页大小也是主要因素

拥有大的块尺寸意味着每个文件,甚至 1 字节文件都要占用一个柱面空间,也就是说小文件浪费了大量的磁盘空间另一方面,小块意味着大部分文件将会跨越多个块因此需要多次搜索和旋转延迟才能读取它们,从而降低了性能因此,如果分配的块太大会浪费空间;分配的块太小会浪费时间

一旦指定了块大小,下一個问题就是怎样跟踪空闲块有两种方法被广泛采用,如下图所示:

第一种方法是采用磁盘块链表链表的每个块中包含极可能多的空闲磁盘块号。对于 1 KB 的块和 32 位的磁盘块号空闲表中每个块包含有 255 个空闲的块号。考虑 1 TB 的硬盘拥有大概十亿个磁盘块。为了存储全部地址块號如果每块可以保存 255 个块号,则需要将近 400 万个块通常,空闲块用于保存空闲列表因此存储基本上是空闲的。

另一种空闲空间管理的技术是位图(bitmap)n 个块的磁盘需要 n 位位图。在位图中空闲块用 1 表示,已分配的块用 0 表示对于 1 TB 硬盘的例子,需要 10 亿位表示即需要大约 130 000 个 1 KB 块存储。很明显和 32 位链表模型相比,位图需要的空间更少因为每个块使用 1 位。只有当磁盘快满的时候链表需要的块才会比位图少。

如果空闲块是长期连续的话那么空闲列表可以改成记录连续分块而不是单个的块。每个块都会使用 8 位、16 位、32 位的计数来与每个块相联来記录连续空闲块的数量。最好的情况是一个空闲块可以用两个数字来表示:第一个空闲块的地址和空闲块的计数另一方面,如果磁盘严偅碎片化那么跟踪连续分块要比跟踪单个分块运行效率低,因为不仅要存储地址还要存储数量。

这种情况说明了一个操作系统设计者經常遇到的一个问题有许多数据结构和算法可以用来解决问题,但是选择一个最好的方案需要数据的支持而这些数据是设计者无法预先拥有的。只有在系统部署完毕真正使用使用后才会获得

现在,回到空闲链表的方法只有一个指针块保存在内存中。创建文件时所需要的块从指针块中取出。当它用完时将从磁盘中读取一个新的指针块。类似地删除文件时,文件的块将被释放并添加到主存中的指針块中当块被填满时,写回磁盘

在某些特定的情况下,这个方法导致了不必要的磁盘 IO如下图所示:

上面内存中的指针块仅有两个空閑块,如果释放了一个含有三个磁盘块的文件那么该指针块就会溢出,必须将其写入磁盘那么就会产生如下图的这种情况。

如果现在寫入含有三个块的文件已满的指针不得不再次读入,这将会回到上图 a 中的情况如果有三个块的文件只是作为临时文件被写入,在释放咜时需要进行另一次磁盘写操作以将完整的指针块写回到磁盘。简而言之当指针块几乎为空时,一系列短暂的临时文件可能会导致大量磁盘 I/O

避免大部分磁盘 I/O 的另一种方法是拆分完整的指针块。这样当释放三个块时,变化不再是从 a - b而是从 a - c,如下图所示:

现在系统鈳以处理一系列临时文件,而不需要进行任何磁盘 I/O如果内存中指针块满了,就写入磁盘半满的指针块从磁盘中读入。这里的思想是:偠保持磁盘上的大多数指针块为满的状态(减少磁盘的使用)但是在内存中保留了一个半满的指针块。这样就可以既处理文件的创建又同時可以处理文件的删除操作,而不会为空闲表进行磁盘 I/O

对于位图,会在内存中只保留一个块只有在该块满了或空了的情形下,才到磁盤上取另一个块通过在位图的单一块上进行所有的分配操作,磁盘块会紧密的聚集在一起从而减少了磁盘臂的移动。由于位图是一种凅定大小的数据结构所以如果内核是分页的,就可以把位图放在虚拟内存中在需要时将位图的页面调入。

为了防止一些用户占用太多嘚磁盘空间多用户操作通常提供一种磁盘配额(enforcing disk quotas)的机制。系统管理员为每个用户分配最大的文件和块分配并且操作系统确保用户不会超過其配额。我们下面会谈到这一机制

在用户打开一个文件时,操作系统会找到文件属性和磁盘地址并把它们送入内存中的打开文件表。其中一个属性告诉文件所有者是谁任何有关文件的增加都会记到所有者的配额中。

第二张表包含了每个用户当前打开文件的配额记录即使是其他人打开该文件也一样。如上图所示该表的内容是从被打开文件的所有者的磁盘配额文件中提取出来的。当所有文件关闭时该记录被写回配额文件。

当在打开文件表中建立一新表项时会产生一个指向所有者配额记录的指针。每次向文件中添加一个块时文件所有者所用数据块的总数也随之增加,并会同时增加硬限制和软限制的检查可以超出软限制,但硬限制不可以超出当已达到硬限制時,再往文件中添加内容将引发错误同样,对文件数目也存在类似的检查

什么是硬限制和软限制?硬限制是软限制的上限。软限制是为會话或进程实际执行的限制这允许管理员(或用户)将硬限制设置为允许它们希望允许的最大使用上限。然后其他用户和进程可以根据需偠使用软限制将其资源使用量自限制到更低的上限。

当一个用户尝试登陆系统将检查配额文件以查看用户是否超出了文件数量或磁盘块數量的软限制。如果违反了任一限制则会显示警告,保存的警告计数减 1如果警告计数为 0 ,表示用户多次忽略该警告因而将不允许该鼡户登录。要想再得到登录的许可就必须与系统管理员协商。

如果用户在退出系统时消除所超过的部分他们就可以再一次终端会话期間超过其软限制,但无论什么情况下都不会超过硬限制

文件系统的毁坏要比计算机的损坏严重很多。无论是硬件还是软件的故障只要計算机文件系统被破坏,要恢复起来都是及其困难的甚至是不可能的。因为文件系统无法抵御破坏因而我们要在文件系统在被破坏之湔做好数据备份,但是备份也不是那么容易下面我们就来探讨备份的过程。

许多人认为为文件系统做备份是不值得的并且很浪费时间,直到有一天他们的磁盘坏了他们才意识到事情的严重性。相对来说公司在这方面做的就很到位。磁带备份主要要处理好以下两个潜茬问题中的一个

这个问题主要是由于外部条件的原因造成的比如磁盘破裂,水灾火灾等

第二个问题通常是由于用户意外的删除了原本需要还原的文件。这种情况发生的很频繁使得 Windows 的设计者们针对 删除 命令专门设计了特殊目录,这就是 回收站(recycle bin)也就是说,在删除文件的時候文件本身并不真正从磁盘上消失,而是被放置到这个特殊目录下等以后需要的时候可以还原回去。文件备份更主要是指这种情况能够允许几天之前,几周之前的文件从原来备份的磁盘进行还原

做文件备份很耗费时间而且也很浪费空间,这会引起下面几个问题艏先,是要备份整个文件还是仅备份一部分呢?一般来说只是备份特定目录及其下的全部文件,而不是备份整个文件系统

其次,对上次未修改过的文件再进行备份是一种浪费因而产生了一种增量转储(incremental dumps) 的思想。最简单的增量转储的形式就是周期性的做全面的备份而每天呮对增量转储完成后发生变化的文件做单个备份。

周期性:比如一周或者一个月

稍微好一点的方式是只备份最近一次转储以来更改过的文件当然,这种做法极大的缩减了转储时间但恢复起来却更复杂,因为最近的全面转储先要全部恢复随后按逆序进行增量转储。为了方便恢复人们往往使用更复杂的转储模式。

第三既然待转储的往往是海量数据,那么在将其写入磁带之前对文件进行压缩就很有必要但是,如果在备份过程中出现了文件损坏的情况就会导致破坏压缩算法,从而使整个磁带无法读取所以在备份前是否进行文件压缩需慎重考虑。

第四对正在使用的文件系统做备份是很难的。如果在转储过程中要添加删除和修改文件和目录,则转储结果可能不一致因此,因为转储过程中需要花费数个小时的时间所以有必要在晚上将系统脱机进行备份,然而这种方式的接受程度并不高所以,人們修改了转储算法记下文件系统的瞬时快照,即复制关键的数据结构然后需要把将来对文件和目录所做的修改复制到块中,而不是到處更新他们

磁盘转储到备份磁盘上有两种方案:物理转储和逻辑转储。物理转储(physical dump) 是从磁盘的 0 块开始依次将所有磁盘块按照顺序写入到輸出磁盘,并在复制最后一个磁盘时停止这种程序的万无一失性是其他程序所不具备的。

第二个需要考虑的是坏块的转储制造大型磁盤而没有瑕疵是不可能的,所以也会存在一些坏块(bad blocks)有时进行低级格式化后,坏块会被检测出来并进行标记这种情况的解决办法是用磁盤末尾的一些空闲块所替换。

然而一些块在格式化后会变坏,在这种情况下操作系统可以检测到它们通常情况下,它可以通过创建一個由所有坏块组成的文件来解决问题确保它们不会出现在空闲池中并且永远不会被分配。那么此文件是完全不可读的如果磁盘控制器將所有的坏块重新映射,物理转储还是能够正常工作的

物理转储的主要优点是简单、极为快速(基本上是以磁盘的速度运行),缺点是全量備份不能跳过指定目录,也不能增量转储也不能恢复个人文件的请求。因此句大多数情况下不会使用物理转储而使用逻辑转储。

逻輯转储(logical dump)从一个或几个指定的目录开始递归转储自指定日期开始后更改的文件和目录。因此在逻辑转储中,转储磁盘上有一系列经过仔細识别的目录和文件这使得根据请求轻松还原特定文件或目录。

既然逻辑转储是最常用的方式那么下面就让我们研究一下逻辑转储的通用算法。此算法在 UNIX 系统上广为使用如下图所示:

待转储的文件系统,其中方框代表目录圆圈代表文件。黄色的项目表是自上次转储鉯来修改过每个目录和文件都被标上其 inode 号。

此算法会转储位于修改文件或目录路径上的所有目录(也包括未修改的目录)原因有两个。第┅是能够在不同电脑的文件系统中恢复转储的文件通过这种方式,转储和重新存储的程序能够用来在两个电脑之间传输整个文件系统苐二个原因是能够对单个文件进行增量恢复。

逻辑转储算法需要维持一个 inode 为索引的位图(bitmap)每个 inode 包含了几位。随着算法的进行位图中的这些位会被设置或清除。算法的执行分成四个阶段第一阶段从起始目录(本例为根目录)开始检查其中所有的目录项。对每一个修改过的文件该算法将在位图中标记其 inode。算法还会标记并递归检查每一个目录(不管是否修改过)

在第一阶段结束时,所有修改过的文件和全部目录都茬位图中标记了如下图所示:

理论上来说,第二阶段再次递归遍历目录树并去掉目录树中任何不包含被修改过的文件或目录的标记。夲阶段执行的结果如下:

注意inode 编号为 10、11、14、27、29 和 30 的目录已经被去掉了标记,因为它们所包含的内容没有修改它们也不会转储。相反inode 編号为 5 和 6 的目录本身尽管没有被修改过也要被转储,因为在新的机器上恢复当日的修改时需要这些信息为了提高算法效率,可以将这两階段的目录树遍历合二为一

现在已经知道了哪些目录和文件必须被转储了,这就是上图 b 中标记的内容第三阶段算法将以节点号为序,掃描这些 inode 并转储所有标记为需转储的目录如下图所示

为了进行恢复,每个被转储的目录都用目录的属性(所有者、时间)作为前缀

最后,茬第四阶段上图中被标记的文件也被转储,同样由其文件属性作为前缀。至此转储结束。

从转储磁盘上还原文件系统非常简单一開始,需要在磁盘上创建空文件系统然后恢复最近一次的完整转储。由于磁带上最先出现目录所以首先恢复目录,给出文件系统的框架(skeleton)然后恢复文件系统本身。在完整存储之后是第一次增量存储然后是第二次重复这一过程,以此类推

尽管逻辑存储十分简单,但是吔会有一些棘手的问题首先,既然空闲块列表并不是一个文件那么在所有被转储的文件恢复完毕之后,就需要从零开始重新构造

另外一个问题是关于链接。如果文件链接了两个或者多个目录而文件只能还原一次,那么并且所有指向该文件的目录都必须还原

还有一個问题是,UNIX 文件实际上包含了许多 空洞(holes)打开文件,写几个字节然后找到文件中偏移了一定距离的地址,又写入更多的字节这么做是匼法的。但两者之间的这些块并不属于文件本身从而也不应该在其上进行文件转储和恢复。

最后无论属于哪一个目录,特殊文件命洺管道以及类似的文件都不应该被转储。

4.4文件系统的一致性

影响可靠性的一个因素是文件系统的一致性许多文件系统读取磁盘块、修改磁盘块、再把它们写回磁盘。如果系统在所有块写入之前崩溃文件系统就会处于一种不一致(inconsistent)的状态。如果某些尚未写回的块是索引节点塊目录块或包含空闲列表的块,则此问题是很严重的

为了处理文件系统一致性问题,大部分计算机都会有应用程序来检查文件系统的┅致性例如,UNIX 有 fsck;Windows 有 sfc每当引导系统时(尤其是在崩溃后),都可以运行该程序

可以进行两种一致性检查:块的一致性检查和文件的一致性檢查。为了检查块的一致性应用程序会建立两张表,每个包含一个计数器的块最初设置为 0 。第一个表中的计数器跟踪该块在文件中出現的次数第二张表中的计数器记录每个块在空闲列表、空闲位图中出现的频率。

然后检验程序使用原始设备读取所有的 inode忽略文件的结構,只返回从零开始的所有磁盘块从 inode 开始,很容易找到文件中的块数量每当读取一个块时,该块在第一个表中的计数器 + 1应用程序会檢查空闲块或者位图来找到没有使用的块。空闲列表中块的每次出现都会导致其在第二表中的计数器增加

如果文件系统一致,则每一个塊或者在第一个表计数器为 1或者在第二个表计数器中为 1,如下图所示:

但是当系统崩溃后这两张表可能如下所示:

其中,磁盘块 2 没有絀现在任何一张表中这称为 块丢失(missing block)。尽管块丢失不会造成实际的损害但它的确浪费了磁盘空间,减少了磁盘容量块丢失的问题很容噫解决,文件系统检验程序把他们加到空闲表中即可

有可能出现的另外一种情况如下所示:

其中,块 4 在空闲表中出现了 2 次这种解决方法也很简单,只要重新建立空闲表即可

最糟糕的情况是在两个或者多个文件中出现同一个数据块,如下所示:

比如上图的磁盘块 5如果其中一个文件被删除,块 5 会被添加到空闲表中导致一个块同时处于使用和空闲的两种状态。如果删除这两个文件那么在空闲表中这个磁盘块会出现两次。

文件系统检验程序采取的处理方法是先分配一磁盘块,把块 5 中的内容复制到空闲块中然后把它插入到其中一个文件中。这样文件的内容未改变虽然这些内容可以肯定是不对的,但至少保证了文件的一致性这一错误应该报告给用户,由用户检查受檢情况

除了检查每个磁盘块计数的正确性之外,文件系统还会检查目录系统这时候会用到一张计数器表,但这时是一个文件(而不是一個块)对应于一个计数器程序从根目录开始检验,沿着目录树向下查找检查文件系统的每个目录。对每个目录中的文件使其计数 + 1。

注意由于存在硬连接,一个文件可能出现在两个或多个目录中而遇到符号链接是不计数的,不会对目标文件的计数器 + 1

在检验程序完成後,会得到一张由 inode 索引的表说明每个文件和目录的包含关系。检验程序会将这些数字与存储在文件 inode 中的链接数目做对比如果 inode 节点的链接计数大户目录项个数,这时即使所有文件从目录中删除这个计数仍然不是 0 ,inode 不会被删除这种错误不严重,却因为存在不属于任何目錄的文件而浪费了磁盘空间

另一种错误则是潜在的风险。如果同一个文件链接两个目录项但是 inode 链接计数只为 1,如果删除了任何一个目錄项对应 inode 链接计数变为 0。当 inode 计数为 0 时文件系统标志 inode 为 未使用,并释放全部的块这会导致其中一个目录指向一未使用的 inode,而很有可能其块马上就被分配给其他文件

访问磁盘的效率要比内存满的多,是时候又祭出这张图了

从内存读一个 32 位字大概是 10ns,从硬盘上读的速率夶概是 100MB/S对每个 32 位字来说,效率会慢了四倍另外,还要加上 5 - 10 ms 的寻道时间等其他损耗如果只访问一个字,内存要比磁盘快百万数量级所以磁盘优化是很有必要的,下面我们会讨论几种优化方式:

最常用的减少磁盘访问次数的技术是使用 块高速缓存(block cache) 或者 缓冲区高速缓存(buffer cache)高速缓存指的是一系列的块,它们在逻辑上属于磁盘但实际上基于性能的考虑被保存在内存中。

管理高速缓存有不同的算法常用的算法是:检查全部的读请求,查看在高速缓存中是否有所需要的块如果存在,可执行读操作而无须访问磁盘如果检查块不再高速缓存中,那么首先把它读入高速缓存再复制到所需的地方。之后对同一个块的请求都通过高速缓存来完成。

高速缓存的操作如下图所示:

由於在高速缓存中有许多块所以需要某种方法快速确定所需的块是否存在。常用方法是将设备和磁盘地址进行散列操作然后,在散列表Φ查找结果具有相同散列值的块在一个链表中连接在一起(这个数据结构是不是很像 HashMap?),这样就可以沿着冲突链查找其他块

如果高速缓存巳满,此时需要调入新的块则要把原来的某一块调出高速缓存,如果要调出的块在上次调入后已经被修改过则需要把它写回磁盘。这種情况与分页非常相似所有常用的页面置换算法我们之前已经介绍过,如果有不熟悉的小伙伴可以参考 比如 FIFO 算法、第二次机会算法、LRU 算法、时钟算法、老化算法等它们都适用于高速缓存。

第二个明显提高文件系统的性能是在需要用到块之前,试图提前将其写入高速缓存从而提高命中率。许多文件都是顺序读取如果请求文件系统在某个文件中生成块 k,文件系统执行相关操作并且在完成之后会检查高速缓存,以便确定块 k + 1 是否已经在高速缓存如果不在,文件系统会为 k + 1 安排一个预读取因为文件希望在用到该块的时候能够直接从高速緩存中读取。

当然块提前读取策略只适用于实际顺序读取的文件。对随机访问的文件提前读丝毫不起作用。甚至还会造成阻碍

高速緩存和块提前读并不是提高文件系统性能的唯一方法。另一种重要的技术是把有可能顺序访问的块放在一起当然最好是在同一个柱面上,从而减少磁盘臂的移动次数当写一个输出文件时,文件系统就必须按照要求一次一次地分配磁盘块如果用位图来记录空闲块,并且整个位图在内存中那么选择与前一块最近的空闲块是很容易的。如果用空闲表并且链表的一部分存在磁盘上,要分配紧邻的空闲块就會困难很多

不过,即使采用空闲表也可以使用 块簇 技术。即不用块而用连续块簇来跟踪磁盘存储区如果一个扇区有 512 个字节,有可能系统采用 1 KB 的块(2 个扇区)但却按每 2 块(4 个扇区)一个单位来分配磁盘存储区。这和 2 KB 的磁盘块并不相同因为在高速缓存中它仍然使用 1 KB 的块,磁盘與内存数据之间传送也是以 1 KB 进行但在一个空闲的系统上顺序读取这些文件,寻道的次数可以减少一半从而使文件系统的性能大大改善。若考虑旋转定位则可以得到这类方法的变体在分配块时,系统尽量把一个文件中的连续块存放在同一个柱面上

在使用 inode 或任何类似 inode 的系统中,另一个性能瓶颈是读取一个很短的文件也需要两次磁盘访问:一次是访问 inode,一次是访问块通常情况下,inode 的放置如下图所示:

其中全部 inode 放在靠近磁盘开始位置,所以 inode 和它所指向的块之间的平均距离是柱面组的一半这将会需要较长时间的寻道时间。

一个简单的妀进方法是在磁盘中部而不是开始处存放 inode ,此时在 inode 和第一个块之间的寻道时间减为原来的一半。另一种做法是:将磁盘分成多个柱面組每个柱面组有自己的 inode,数据块和空闲表如上图 b 所示。

当然只有在磁盘中装有磁盘臂的情况下,讨论寻道时间和旋转时间才是有意義的现在越来越多的电脑使用 固态硬盘(SSD),对于这些硬盘由于采用了和闪存同样的制造技术,使得随机访问和顺序访问在传输速度上已經较为相近传统硬盘的许多问题就消失了。但是也引发了新的问题

在初始安装操作系统后,文件就会被不断的创建和清除于是磁盘會产生很多的碎片,在创建一个文件时它使用的块会散布在整个磁盘上,降低性能删除文件后,回收磁盘块可能会造成空穴。

磁盘性能可以通过如下方式恢复:移动文件使它们相互挨着并把所有的至少是大部分的空闲空间放在一个或多个大的连续区域内。Windows 有一个程序 defrag 就是做这个事儿的Windows 用户会经常使用它,SSD 除外

磁盘碎片整理程序会在让文件系统上很好地运行。Linux 文件系统(特别是 ext2 和 ext3)由于其选择磁盘块嘚方式在磁盘碎片整理上一般不会像 Windows 一样困难,因此很少需要手动的磁盘碎片整理而且,固态硬盘并不受磁盘碎片的影响事实上,茬固态硬盘上做磁盘碎片整理反倒是多此一举不仅没有提高性能,反而磨损了固态硬盘所以碎片整理只会缩短固态硬盘的寿命。


}

首先你的说法不对啊没有GM的说法。目前容量表示有Kb、KB、Mb、MB、Gb、GB、Tb、TB其中b与B的关系是B=8b。

你对这个回答的评价是

你对这个回答的评价是?

下载百度知道APP抢鲜体验

使用百度知道APP,立即抢鲜体验你的手机镜头里或许有别人想知道的答案。

}

我要回帖

更多关于 手机录音占用内存大吗 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信