专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

全面剖析Linux文件系统

  在Linux中,最直观、最可见的部分就是文件系统(filesystem)。下面我们就来一起探讨一下关于Linux中国的文件系统,系统调用以及文件系统实现背后的原理和思想。这些思想中有一些来源于MULTICS,现在已经被Windows等其他操作系统使用。Linux的设计理念就是小的就是好的(SmallisBeautiful)。虽然Linux只是使用了最简单的机制和少量的系统调用,但是Linux却提供了强大而优雅的文件系统。Linux文件系统基本概念
  Linux在最初的设计是MINIX1文件系统,它只支持14字节的文件名,它的最大文件只支持到64MB。在MINIX1之后的文件系统是ext文件系统。ext系统相较于MINIX1来说,在支持字节大小和文件大小上均有很大提升,但是ext的速度仍没有MINIX1快,于是,ext2被开发出来,它能够支持长文件名和大文件,而且具有比MINIX1更好的性能。这使他成为Linux的主要文件系统。只不过Linux会使用VFS曾支持多种文件系统。在Linux链接时,用户可以动态的将不同的文件系统挂载倒VFS上。
  Linux中的文件是一个任意长度的字节序列,Linux中的文件可以包含任意信息,比如ASCII码、二进制文件和其他类型的文件是不加区分的。
  为了方便起见,文件可以被组织在一个目录中,目录存储成文件的形式在很大程度上可以作为文件处理。目录可以有子目录,这样形成有层次的文件系统,Linux系统下面的根目录是,它通常包含了多个子目录。字符还用于对目录名进行区分,例如usrcxuan表示的就是根目录下面的usr目录,其中有一个叫做cxuan的子目录。
  下面我们介绍一下Linux系统根目录下面的目录名bin,它是重要的二进制应用程序,包含二进制文件,系统的所有用户使用的命令都在这里boot,启动包含引导加载程序的相关文件dev,包含设备文件,终端文件,USB或者连接到系统的任何设备etc,配置文件,启动脚本等,包含所有程序所需要的配置文件,也包含了启动停止单个应用程序的启动和关闭shell脚本home,本地主要路径,所有用户用home目录存储个人信息lib,系统库文件,包含支持位于bin和sbin下的二进制库文件lostfound,在根目录下提供一个遗失查找系统,必须在root用户下才能查看当前目录下的内容media,挂载可移动介质mnt,挂载文件系统opt,提供一个可选的应用程序安装目录proc,特殊的动态目录,用于维护系统信息和状态,包括当前运行中进程信息root,root用户的主要目录文件夹sbin,重要的二进制系统文件tmp,系统和用户创建的临时文件,系统重启时,这个目录下的文件都会被删除usr,包含绝大多数用户都能访问的应用程序和文件var,经常变化的文件,诸如日志文件或数据库等
  在Linux中,有两种路径,一种是绝对路径(absolutepath),绝对路径告诉你从根目录下查找文件,绝对路径的缺点是太长而且不太方便。还有一种是相对路径(relativepath),相对路径所在的目录也叫做工作目录(workingdirectory)。
  如果usrlocalbooks是工作目录,那么shell命令brcpbooksbooksreplica
  就表示的是相对路径,而brcpusrlocalbooksbooksusrlocalbooksbooksreplica
  则表示的是绝对路径。
  在Linux中经常出现一个用户使用另一个用户的文件或者使用文件树结构中的文件。两个用户共享同一个文件,这个文件位于某个用户的目录结构中,另一个用户需要使用这个文件时,必须通过绝对路径才能引用到他。如果绝对路径很长,那么每次输入起来会变的非常麻烦,所以Linux提供了一种链接(link)机制。
  举个例子,下面是一个使用链接之前的图
  以上所示,比如有两个工作账户jianshe和cxuan,jianshe想要使用cxuan账户下的A目录,那么它可能会输入usrcxuanA,这是一种未使用链接之后的图。
  使用链接后的示意如下
  现在,jianshe可以创建一个链接来使用cxuan下面的目录了。‘
  当一个目录被创建出来后,有两个目录项也同时被创建出来,它们就是。和。。,前者代表工作目录自身,后者代表该目录的父目录,也就是该目录所在的目录。这样一来,在usrjianshe中访问cxuan中的目录就是。。cxuanxxx
  Linux文件系统不区分磁盘的,这是什么意思呢?一般来说,一个磁盘中的文件系统相互之间保持独立,如果一个文件系统目录想要访问另一个磁盘中的文件系统,在Windows中你可以像下面这样。
  两个文件系统分别在不同的磁盘中,彼此保持独立。
  而在Linux中,是支持挂载的,它允许一个磁盘挂在到另外一个磁盘上,那么上面的关系会变成下面这样
  挂在之后,两个文件系统就不再需要关心文件系统在哪个磁盘上了,两个文件系统彼此可见。
  Linux文件系统的另外一个特性是支持加锁(locking)。在一些应用中会出现两个或者更多的进程同时使用同一个文件的情况,这样很可能会导致竞争条件(racecondition)。一种解决方法是对其进行加不同粒度的锁,就是为了防止某一个进程只修改某一行记录从而导致整个文件都不能使用的情况。
  POSIX提供了一种灵活的、不同粒度级别的锁机制,允许一个进程使用一个不可分割的操作对一个字节或者整个文件进行加锁。加锁机制要求尝试加锁的进程指定其要加锁的文件,开始位置以及要加锁的字节
  Linux系统提供了两种锁:共享锁和互斥锁。如果文件的一部分已经加上了共享锁,那么再加排他锁是不会成功的;如果文件系统的一部分已经被加了互斥锁,那么在互斥锁解除之前的任何加锁都不会成功。为了成功加锁、请求加锁的部分的所有字节都必须是可用的。
  在加锁阶段,进程需要设计好加锁失败后的情况,也就是判断加锁失败后是否选择阻塞,如果选择阻塞式,那么当已经加锁的进程中的锁被删除时,这个进程会解除阻塞并替换锁。如果进程选择非阻塞式的,那么就不会替换这个锁,会立刻从系统调用中返回,标记状态码表示是否加锁成功,然后进程会选择下一个时间再次尝试。
  加锁区域是可以重叠的。下面我们演示了三种不同条件的加锁区域。
  如上图所示,A的共享锁在第四字节到第八字节进行加锁
  如上图所示,进程在A和B上同时加了共享锁,其中68字节是重叠锁
  如上图所示,进程A和B和C同时加了共享锁,那么第六字节和第七字节是共享锁。
  如果此时一个进程尝试在第6个字节处加锁,此时会设置失败并阻塞,由于该区域被ABC同时加锁,那么只有等到ABC都释放锁后,进程才能加锁成功。Linux文件系统调用
  许多系统调用都会和文件与文件系统有关。我们首先先看一下对单个文件的系统调用,然后再来看一下对整个目录和文件的系统调用。
  为了创建一个新的文件,会使用到creat方法,注意没有e。
  这里说一个小插曲,曾经有人问UNIX创始人KenThompson,如果有机会重新写UNIX,你会怎么办,他回答自己要把creat改成create,哈哈哈哈。
  这个系统调用的两个参数是文件名和保护模式brfdcreat(aaa,mode);
  这段命令会创建一个名为aaa的文件,并根据mode设置文件的保护位。这些位决定了哪个用户可能访问文件、如何访问。
  creat系统调用不仅仅创建了一个名为aaa的文件,还会打开这个文件。为了允许后续的系统调用访问这个文件,这个creat系统调用会返回一个非负整数,这个就叫做文件描述符(filedescriptor),也就是上面的fd。
  如果在已经存在的文件上调用了creat系统调用,那么该文件中的内容会被清除,从0开始。通过设置合适的参数,open系统调用也能够创建文件。
  下面让我们看一看主要的系统调用,如下表所示
  系统调用
  描述
  fdcreat(name,mode)
  一种创建一个新文件的方式
  fdopen(file,。。。)
  打开文件读、写或者读写
  sclose(fd)
  关闭一个打开的文件
  nread(fd,buffer,nbytes)
  从文件中向缓存中读入数据
  nwrite(fd,buffer,nbytes)
  从缓存中向文件中写入数据
  positionlseek(fd,offset,whence)
  移动文件指针
  sstat(name,buf)
  获取文件信息
  sfstat(fd,buf)
  获取文件信息
  spipe(fd〔0〕)
  创建一个管道
  sfcntl(fd,。。。)
  文件加锁等其他操作
  为了对一个文件进行读写的前提是先需要打开文件,必须使用creat或者open打开,参数是打开文件的方式,是只读、可读写还是只写。open系统调用也会返回文件描述符。打开文件后,需要使用close系统调用进行关闭。close和open返回的fd总是未被使用的最小数量。
  什么是文件描述符?文件描述符就是一个数字,这个数字标示了计算机操作系统中打开的文件。它描述了数据资源,以及访问资源的方式。
  当程序要求打开一个文件时,内核会进行如下操作授予访问权限在全局文件表(globalfiletable)中创建一个条目(entry)向软件提供条目的位置
  文件描述符由唯一的非负整数组成,系统上每个打开的文件至少存在一个文件描述符。文件描述符最初在Unix中使用,并且被包括Linux,macOS和BSD在内的现代操作系统所使用。
  当一个进程成功访问一个打开的文件时,内核会返回一个文件描述符,这个文件描述符指向全局文件表的entry项。这个文件表项包含文件的inode信息,字节位移,访问限制等。例如下图所示
  默认情况下,前三个文件描述符为STDIN(标准输入)、STDOUT(标准输出)、STDERR(标准错误)。
  标准输入的文件描述符是0,在终端中,默认为用户的键盘输入
  标准输出的文件描述符是1,在终端中,默认为用户的屏幕
  与错误有关的默认数据流是2,在终端中,默认为用户的屏幕。
  在简单聊了一下文件描述符后,我们继续回到文件系统调用的探讨。
  在文件系统调用中,开销最大的就是read和write了。read和write都有三个参数文件描述符:告诉需要对哪一个打开文件进行读取和写入缓冲区地址:告诉数据需要从哪里读取和写入哪里统计:告诉需要传输多少字节
  这就是所有的参数了,这个设计非常简单轻巧。
  虽然几乎所有程序都按顺序读取和写入文件,但是某些程序需要能够随机访问文件的任何部分。与每个文件相关联的是一个指针,该指针指示文件中的当前位置。顺序读取(或写入)时,它通常指向要读取(写入)的下一个字节。如果指针在读取1024个字节之前位于4096的位置,则它将在成功读取系统调用后自动移至5120的位置。
  Lseek系统调用会更改指针位置的值,以便后续对read或write的调用可以在文件中的任何位置开始,甚至可以超出文件末尾。
  lseekLseek,段首大写。
  lseek避免叫做seek的原因就是seek已经在之前16位的计算机上用于搜素功能了。
  Lseek有三个参数:第一个是文件的文件描述符,第二个是文件的位置;第三个告诉文件位置是相对于文件的开头,当前位置还是文件的结尾brlseek(intfildes,offtoffset,intwhence);
  lseek的返回值是更改文件指针后文件中的绝对位置。lseek是唯一从来不会造成真正磁盘查找的系统调用,它只是更新当前的文件位置,这个文件位置就是内存中的数字。
  对于每个文件,Linux都会跟踪文件模式(常规,目录,特殊文件),大小,最后修改时间以及其他信息。程序能够通过stat系统调用看到这些信息。第一个参数就是文件名,第二个是指向要放置请求信息结构的指针。这些结构的属性如下图所示。
  存储文件的设备
  存储文件的设备
  inode编号
  文件模式(包括保护位信息)
  文件链接的数量
  文件所有者标识
  文件所属的组
  文件大小(字节)
  创建时间
  最后一个修改访问时间
  fstat调用和stat相同,只有一点区别,fstat可以对打开文件进行操作,而stat只能对路径进行操作。
  pipe文件系统调用被用来创建shell管道。它会创建一系列的伪文件,来缓冲和管道组件之间的数据,并且返回读取或者写入缓冲区的文件描述符。在管道中,像是如下操作brsortinhead40
  sort进程将会输出到文件描述符1,也就是标准输出,写入管道中,而head进程将从管道中读入。在这种方式中,sort只是从文件描述符0中读取并写入到文件描述符1(管道)中,甚至不知道它们已经被重定向了。如果没有重定向的话,sort会自动的从键盘读入并输出到屏幕中。
  最后一个系统调用是fcntl,它用来锁定和解锁文件,应用共享锁和互斥锁,或者是执行一些文件相关的其他操作。
  现在我们来关心一下和整体目录和文件系统相关的系统调用,而不是把精力放在单个的文件上,下面列出了这些系统调用,我们一起来看一下。
  系统调用
  描述
  smkdir(path,mode)
  创建一个新的目录
  srmdir(path)
  移除一个目录
  slink(oldpath,newpath)
  创建指向已有文件的链接
  sunlink(path)
  取消文件的链接
  schdir(path)
  改变工作目录
  diropendir(path)
  打开一个目录读取
  sclosedir(dir)
  关闭一个目录
  direntreaddir(dir)
  读取一个目录项
  rewinddir(dir)
  回转目录使其在此使用
  可以使用mkdir和rmdir创建和删除目录。但是需要注意,只有目录为空时才可以删除。
  创建一个指向已有文件的链接时会创建一个目录项(directoryentry)。系统调用link来创建链接,oldpath代表已有的路径,newpath代表需要链接的路径,使用unlink可以删除目录项。当文件的最后一个链接被删除时,这个文件会被自动删除。
  使用chdir系统调用可以改变工作目录。
  最后四个系统调用是用于读取目录的。和普通文件类似,他们可以被打开、关闭和读取。每次调用readdir都会以固定的格式返回一个目录项。用户不能对目录执行写操作,但是可以使用creat或者link在文件夹中创建一个目录,或使用unlink删除一个目录。用户不能在目录中查找某个特定文件,但是可以使用rewindir作用于一个打开的目录,使他能在此从头开始读取。Linux文件系统的实现
  下面我们主要讨论一下虚拟文件系统(VirtualFileSystem)。VFS对高层进程和应用程序隐藏了Linux支持的所有文件系统的区别,以及文件系统是存储在本地设备,还是需要通过网络访问远程设备。设备和其他特殊文件和VFS层相关联。接下来,我们就会探讨一下第一个Linux广泛传播的文件系统:ext2。随后,我们就会探讨ext4文件系统所做的改进。各种各样的其他文件系统也正在使用中。所有Linux系统都可以处理多个磁盘分区,每个磁盘分区上都有不同的文件系统。Linux虚拟文件系统
  为了能够使应用程序能够在不同类型的本地或者远程设备上的文件系统进行交互,因为在Linux当中文件系统千奇百种,比较常见的有EXT3、EXT4,还有基于内存的ramfs、tmpfs和基于网络的nfs,和基于用户态的fuse,当然fuse应该不能完全的文件系统,只能算是一个能把文件系统实现放到用户态的模块,满足了内核文件系统的接口,他们都是文件系统的一种实现。对于这些文件系统,Linux做了一层抽象就是VFS虚拟文件系统,
  下表总结了VFS支持的四个主要的文件系统结构。
  对象
  描述
  超级块
  特定的文件系统
  Dentry
  目录项,路径的一个组成部分
  Inode
  特定的文件
  File
  跟一个进程相关联的打开文件
  超级块(superblock)包含了有关文件系统布局的重要信息,超级块如果遭到破坏那么就会导致整个文件系统不可读。
  inode索引节点,包含了每一个文件的描述符。
  在Linux中,目录和设备也表示为文件,因为它们具有对应的inode
  超级块和索引块所在的文件系统都在磁盘上有对应的结构。
  为了便于某些目录操作和路径遍历,比如usrlocalcxuan,VFS支持一个dentry数据结构,该数据结构代表着目录项。这个dentry数据结构有很多东西(http:books。gigatux。nlmirrorkerneldevelopment0672327201ch12lev1sec7。html)这个数据结构由文件系统动态创建。
  目录项被缓存在dentrycache缓存中。例如,缓存条目会缓存usr、usrlocal等条目。如果多个进程通过硬连接访问相同的文件,他们的文件对象将指向此缓存中的相同条目。
  最后,文件数据结构是代表着打开的文件,也代表着内存表示,它根据open系统调用创建。它支持read、write、sendfile、lock和其他在我们之前描述的系统调用中。
  在VFS下实现的实际文件系统不需要在内部使用完全相同的抽象和操作。但是,它们必须在语义上实现与VFS对象指定的文件系统操作相同的文件系统操作。四个VFS对象中每个对象的操作数据结构的元素都是指向基础文件系统中功能的指针。LinuxExt2文件系统
  现在我们一起看一下Linux中最流行的一个磁盘文件系统,那就是ext2。Linux的第一个版本用于MINIX1文件系统,它的文件名大小被限制为最大64MB。MINIX1文件系统被永远的被它的扩展系统ext取代,因为ext允许更长的文件名和文件大小。由于ext的性能低下,ext被其替代者ext2取代,ext2目前仍在广泛使用。
  一个ext2Linux磁盘分区包含了一个文件系统,这个文件系统的布局如下所示
  Boot块也就是第0块不是让Linux使用的,而是用来加载和引导计算机启动代码的。在块0之后,磁盘分区被分成多个组,这些组与磁盘柱面边界所处的位置无关。
  第一个块是超级块(superblock)。它包含有关文件系统布局的信息,包括inode、磁盘块数量和以及空闲磁盘块列表的开始。下一个是组描述符(groupdescriptor),其中包含有关位图的位置,组中空闲块和inode的数量以及组中的目录数量的信息。这些信息很重要,因为ext2会在磁盘上均匀分布目录。
  图中的两个位图用来记录空闲块和空闲inode,这是从MINIX1文件系统继承的选择,大多数UNIX文件系统使用位图而不是空闲列表。每个位图的大小是一个块。如果一个块的大小是1KB,那么就限制了块组的数量是8192个块和8192个inode。块的大小是一个严格的限制,块组的数量不固定,在4KB的块中,块组的数量增大四倍。
  在超级块之后分布的是inode它们自己,inode取值范围是1某些最大值。每个inode是128字节的long,这些字节恰好能够描述一个文件。inode包含了统计信息(包含了stat系统调用能获得的所有者信息,实际上stat就是从inode中读取信息的),以及足够的信息来查找保存文件数据的所有磁盘块。
  在inode之后的是数据块(datablocks)。所有的文件和目录都保存在这。如果一个文件或者目录包含多个块,那么这些块在磁盘中的分布不一定是连续的,也有可能不连续。事实上,大文件块可能会被拆分成很多小块散布在整个磁盘上。
  对应于目录的inode分散在整个磁盘组上。如果有足够的空间,ext2会把普通文件组织到与父目录相同的块组中,而把同一块上的数据文件组织成初始inode节点。位图用来快速确定新文件系统数据的分配位置。在分配新的文件块时,ext2也会给该文件预分配许多额外的数据块,这样可以减少将来向文件写入数据时产生的文件碎片。这种策略在整个磁盘上实现了文件系统的负载,后续还有对文件碎片的排列和整理,而且性能也比较好。
  为了达到访问的目的,需要首先使用Linux系统调用,例如open,这个系统调用会确定打开文件的路径。路径分为两种,相对路径和绝对路径。如果使用相对路径,那么就会从当前目录开始查找,否则就会从根目录进行查找。
  目录文件的文件名最高不能超过255个字符,它的分配如下图所示
  每一个目录都由整数个磁盘块组成,这样目录就可以整体的写入磁盘。在一个目录中,文件和子目录的目录项都是未经排序的,并且一个挨着一个。目录项不能跨越磁盘块,所以通常在每个磁盘块的尾部会有部分未使用的字节。
  上图中每个目录项都由四个固定长度的属性和一个长度可变的属性组成。第一个属性是inode节点数量,文件first的inode编号是19,文件second的编号是42,目录third的inode编号是88。紧随其后的是reclen域,表明目录项大小是多少字节,名称后面会有一些扩展,当名字以未知长度填充时,这个域被用来寻找下一个目录项,直至最后的未使用。这也是图中箭头的含义。紧随其后的是类型域:F表示的是文件,D表示的是目录,最后是固定长度的文件名,上面的文件名的长度依次是5、6、5,最后以文件名结束。
  reclen域是如何扩展的呢?如下图所示
  我们可以看到,中间的second被移除了,所以将其所在的域变为第一个目录项的填充。当然,这个填充可以作为后续的目录项。
  由于目录是按照线性的顺序进行查找的,因此可能需要很长时间才能在大文件末尾找到目录项。因此,系统会为近期的访问目录维护一个缓存。这个缓存用文件名来查找,如果缓存命中,那么就会避免线程搜索这样昂贵的开销。组成路径的每个部分都在目录缓存中保存一个dentry对象,并且通过inode找到后续的路径元素的目录项,直到找到真正的文件inode。
  比如说要使用绝对路径来寻找一个文件,我们暂定这个路径是usrlocalfile,那么需要经过如下几个步骤:首先,系统会确定根目录,它通常使用2号inode,也就是索引2节点,因为索引节点1是ext234文件系统上的坏块索引节点。系统会将一项放在dentry缓存中,以应对将来对根目录的查找。然后,在根目录中查找字符串usr,得到usr目录的inode节点号。usr的inode同样也进入dentry缓存。然后节点被取出,并从中解析出磁盘块,这样就可以读取usr目录并查找字符串local了。一旦找到这个目录项,目录usrlocal的inode节点就可以从中获得。有了usrlocal的inode节点号,就可以读取inode并确定目录所在的磁盘块。最后,从usrlocal目录查找file并确定其inode节点呢号。
  如果文件存在,那么系统会提取inode节点号并把它作为索引在inode节点表中定位相应的inode节点并装入内存。inode被存放在inode节点表(inodetable)中,节点表是一个内核数据结构,它会持有当前打开文件和目录的inode节点号。下面是一些Linux文件系统支持的inode数据结构。
  属性
  字节
  描述
  Mode
  2hr文件属性、保护位、setuid和setgid位
  Nlinks
  2hr指向inode节点目录项的数目
  Uid
  2hr文件所有者的UID
  Gid
  2hr文件所有者的GID
  Size
  4hr文件字节大小
  Addr
  60hr12个磁盘块以及后面3个间接块的地址
  Gen
  1hr每次重复使用inode时增加的代号
  Atime
  4hr最近访问文件的时间
  Mtime
  4hr最近修改文件的时间
  Ctime
  4hr最近更改inode的时间
  现在我们来一起探讨一下文件读取过程,还记得read函数是如何调用的吗?brnread(fd,buffer,nbytes);
  当内核接管后,它会从这三个参数以及内部表与用户有关的信息开始。内部表的其中一项是文件描述符数组。文件描述符数组用文件描述符作为索引并为每一个打开文件保存一个表项。
  文件是和inode节点号相关的。那么如何通过一个文件描述符找到文件对应的inode节点呢?
  这里使用的一种设计思想是在文件描述符表和inode节点表之间插入一个新的表,叫做打开文件描述符(openfiledescriptiontable)。文件的读写位置会在打开文件描述符表中存在,如下图所示
  我们使用shell、P1和P2来描述一下父进程、子进程、子进程的关系。Shell首先生成P1,P1的数据结构就是Shell的一个副本,因此两者都指向相同的打开文件描述符的表项。当P1运行完成后,Shell的文件描述符仍会指向P1文件位置的打开文件描述。然后Shell生成了P2,新的子进程自动继承文件的读写位置,甚至P2和Shell都不知道文件具体的读写位置。
  上面描述的是父进程和子进程这两个相关进程,如果是一个不相关进程打开文件时,它将得到自己的打开文件描述符表项,以及自己的文件读写位置,这是我们需要的。
  因此,打开文件描述符相当于是给相关进程提供同一个读写位置,而给不相关进程提供各自私有的位置。
  inode包含三个间接块的磁盘地址,它们每个指向磁盘块的地址所能够存储的大小不一样。LinuxExt4文件系统
  为了防止由于系统崩溃和电源故障造成的数据丢失,ext2系统必须在每个数据块创建之后立即将其写入到磁盘上,磁盘磁头寻道操作导致的延迟是无法让人忍受的。为了增强文件系统的健壮性,Linux依靠日志文件系统,ext3是一个日志文件系统,它在ext2文件系统的基础之上做了改进,ext4也是ext3的改进,ext4也是一个日志文件系统。ext4改变了ext3的块寻址方案,从而支持更大的文件和更大的文件系统大小。下面我们就来描述一下ext4文件系统的特性。
  具有记录的文件系统最基本的功能就是记录日志,这个日志记录了按照顺序描述所有文件系统的操作。通过顺序写出文件系统数据或元数据的更改,操作不受磁盘访问期间磁盘头移动的开销。最终,这个变更会写入并提交到合适的磁盘位置上。如果这个变更在提交到磁盘前文件系统宕机了,那么在重启期间,系统会检测到文件系统未正确卸载,那么就会遍历日志并应用日志的记录来对文件系统进行更改。
  Ext4文件系统被设计用来高度匹配ext2和ext3文件系统的,尽管ext4文件系统在内核数据结构和磁盘布局上都做了变更。尽管如此,一个文件系统能够从ext2文件系统上卸载后成功的挂载到ext4文件系统上,并提供合适的日志记录。
  日志是作为循环缓冲区管理的文件。日志可以存储在与主文件系统相同或者不同的设备上。日志记录的读写操作会由单独的JBD(JournalingBlockDevice)来扮演。
  JBD中有三个主要的数据结构,分别是logrecord(日志记录)、原子操作和事务。一个日志记录描述了一个低级别的文件系统操作,这个操作通常导致块内的变化。因为像是write这种系统调用会包含多个地方的改动inode节点,现有的文件块,新的文件块和空闲列表等。相关的日志记录会以原子性的方式分组。ext4会通知系统调用进程的开始和结束,以此使JBD能够确保原子操作的记录都能被应用,或者一个也不被应用。最后,主要从效率方面考虑,JBD会视原子操作的集合为事务。一个事务中的日志记录是连续存储的。只有在所有的变更一起应用到磁盘后,日志记录才能够被丢弃。
  由于为每个磁盘写出日志的开销会很大,所以ext4可以配置为保留所有磁盘更改的日志,或者仅仅保留与文件系统元数据相关的日志更改。仅仅记录元数据可以减少系统开销,提升性能,但不能保证不会损坏文件数据。其他的几个日志系统维护着一系列元数据操作的日志,例如SGI的XFS。proc文件系统
  另外一个Linux文件系统是proc(process)文件系统
  它的主要思想来源于贝尔实验室开发的第8版的UNIX,后来被BSD和SystemV采用。
  然而,Linux在一些方面上对这个想法进行了扩充。它的基本概念是为系统中的每个进程在proc中创建一个目录。目录的名字就是进程PID,以十进制数进行表示。例如,proc1024就是一个进程号为1024的目录。在该目录下是进程信息相关的文件,比如进程的命令行、环境变量和信号掩码等。事实上,这些文件在磁盘上并不存在磁盘中。当需要这些信息的时候,系统会按需从进程中读取,并以标准格式返回给用户。
  许多Linux扩展与proc中的其他文件和目录有关。它们包含各种各样的关于CPU、磁盘分区、设备、中断向量、内核计数器、文件系统、已加载模块等信息。非特权用户可以读取很多这样的信息,于是就可以通过一种安全的方式了解系统情况。NFS网络文件系统
  从一开始,网络就在Linux中扮演了很重要的作用。下面我们会探讨一下NFS(NetworkFileSystem)网络文件系统,它在现代Linux操作系统的作用是将不同计算机上的不同文件系统链接成一个逻辑整体。NFS架构
  NFS最基本的思想是允许任意选定的一些客户端和服务器共享一个公共文件系统。在许多情况下,所有的客户端和服务器都会在同一个LAN(LocalAreaNetwork)局域网内共享,但是这并不是必须的。也可能是下面这样的情况:如果客户端和服务器距离较远,那么它们也可以在广域网上运行。客户端可以是服务器,服务器可以是客户端,但是为了简单起见,我们说的客户端就是消费服务,而服务器就是提供服务的角度来聊。
  每一个NFS服务都会导出一个或者多个目录供远程客户端访问。当一个目录可用时,它的所有子目录也可用。因此,通常整个目录树都会作为一个整体导出。服务器导出的目录列表会用一个文件来维护,这个文件是etcexports,当服务器启动后,这些目录可以自动的被导出。客户端通过挂载这些导出的目录来访问它们。当一个客户端挂载了一个远程目录,这个目录就成为客户端目录层次的一部分,如下图所示。
  在这个示例中,一号客户机挂载到服务器的bin目录下,因此它现在可以使用shell访问bincat或者其他任何一个目录。同样,客户机1也可以挂载到二号服务器上从而访问usrlocalprojectsproj1或者其他目录。二号客户机同样可以挂载到二号服务器上,访问路径是mntprojectsproj2。
  从上面可以看到,由于不同的客户端将文件挂载到各自目录树的不同位置,同一个文件在不同的客户端有不同的访问路径和不同的名字。挂载点一般通常在客户端本地,服务器不知道任何一个挂载点的存在。NFS协议
  由于NFS的协议之一是支持异构系统,客户端和服务器可能在不同的硬件上运行不同的操作系统,因此有必要在服务器和客户端之间进行接口定义。这样才能让任何写一个新客户端能够和现有的服务器一起正常工作,反之亦然。
  NFS就通过定义两个客户端服务器协议从而实现了这个目标。协议就是客户端发送给服务器的一连串的请求,以及服务器发送回客户端的相应答复。
  第一个NFS协议是处理挂载。客户端可以向服务器发送路径名并且请求服务器是否能够将服务器的目录挂载到自己目录层次上。因为服务器不关心挂载到哪里,因此请求不会包含挂载地址。如果路径名是合法的并且指定的目录已经被导出,那么服务器会将文件句柄返回给客户端。
  文件句柄包含唯一标识文件系统类型,磁盘,目录的i节点号和安全性信息的字段。
  随后调用读取和写入已安装目录或其任何子目录中的文件,都将使用文件句柄。
  当Linux启动时会在多用户之前运行shell脚本etcrc。可以将挂载远程文件系统的命令写入该脚本中,这样就可以在允许用户登陆之前自动挂载必要的远程文件系统。大部分Linux版本是支持自动挂载的。这个特性会支持将远程目录和本地目录进行关联。
  相对于手动挂载到etcrc目录下,自动挂载具有以下优势如果列出的etcrc目录下出现了某种故障,那么客户端将无法启动,或者启动会很困难、延迟或者伴随一些出错信息,如果客户根本不需要这个服务器,那么手动做了这些工作就白费了。允许客户端并行的尝试一组服务器,可以实现一定程度的容错率,并且性能也可以得到提高。
  另一方面,我们默认在自动挂载时所有可选的文件系统都是相同的。由于NFS不提供对文件或目录复制的支持,用户需要自己确保这些所有的文件系统都是相同的。因此,大部分的自动挂载都只应用于二进制文件和很少改动的只读的文件系统。
  第二个NFS协议是为文件和目录的访问而设计的。客户端能够通过向服务器发送消息来操作目录和读写文件。客户端也可以访问文件属性,比如文件模式、大小、上次修改时间。NFS支持大多数的Linux系统调用,但是open和close系统调用却不支持。
  不支持open和close并不是一种疏忽,而是一种刻意的设计,完全没有必要在读一个文件之前对其进行打开,也没有必要在读完时对其进行关闭。
  NFS使用了标准的UNIX保护机制,使用rwx位来标示所有者(owner)、组(groups)、其他用户。最初,每个请求消息都会携带调用者的groupId和userId,NFS会对其进行验证。事实上,它会信任客户端不会发生欺骗行为。可以使用公钥密码来创建一个安全密钥,在每次请求和应答中使用它验证客户端和服务器。NFS实现
  即使客户端和服务器的代码实现是独立于NFS协议的,大部分的Linux系统会使用一个下图的三层实现,顶层是系统调用层,系统调用层能够处理open、read、close这类的系统调用。在解析和参数检查结束后调用第二层,虚拟文件系统(VFS)层。
  VFS层的任务是维护一个表,每个已经打开的文件都在表中有一个表项。VFS层为每一个打开的文件维护着一个虚拟i节点,简称为vnode。v节点用来说明文件是本地文件还是远程文件。如果是远程文件的话,那么vnode会提供足够的信息使客户端能够访问它们。对于本地文件,会记录其所在的文件系统和文件的inode,因为现代操作系统能够支持多文件系统。虽然VFS是为了支持NFS而设计的,但是现代操作系统都会使用VFS,而不管有没有NFS。
  如果文章对你有帮助,希望各位小伙伴们交出你的三连呀!

春天来了,又想去徽州了前段时间,徽州鱼灯刷爆了互联网,一时间把中国人的浪漫氛围感拉到了顶峰。春天啊,总是要有点浪漫在的。看完给我的感觉就是,被美到心颤。图源微博蘑菇张NKU春雨一阵阵落下,在已经来临的春杭州知名的地标建筑之一,有过一段神仙佳话,游玩不要错过了杭州雷峰塔位于杭州市西湖畔,是中国南方最有名的古建筑之一,也是杭州的重要景点之一。作为一座古老的塔楼,雷峰塔历史悠久文化底蕴深厚,吸引了无数国内外游客前来参观。雷峰塔始建于北宋太平永不消失的岁月之光单县历史人文视点走笔浮龙湖景区的双圣亭老城区的壁画单县景区景点星罗棋布,所呈现的历史人文元素不胜枚举。幵山景区位于古孟渚泽遗址的北边。幵山的幵字,康熙字典解释为平原上的土丘,因为建设之初挖出一块刻有幵人生最美的风景,就是知足常乐作者子墨春花烂漫,春雨绵绵,最美的季节,有着最美的风景,人生之中,最好的拥有,就是季节更迭,最真的情感,就是生命的牵念。三月,春色正浓,潋滟了时光,花开满园,花香鸟语,一派春暖花开绿色走廊里的经济能量贵州六盘水1400米海拔之上的绿色纺织园区编者按从最高海拔2900。6米,到最低海拔147。8米的贵州,四季分明景色各异,森林覆盖率达62。12,被誉为中国的绿色走廊。如今,在两山理念的指引下,这条绿色走廊里不断涌现以节能樱花玉兰郁金香收好这张赏花地图,与春天撞个满怀!三月的风,揉揉拂面,和煦爽心。三月的阳光,温和不燥,透心舒坦。阳春三月,万物复苏,绿树成荫,花开成海,莺歌燕舞,大地一片生机勃勃的景象。三月,让我们一起来倾听花开的声音!外滩在外滩贵州织金梨花绽放香满园来源人民网贵州频道绽放枝头的梨花。游客拍摄桃花红梨花白的春天美景。游客拍摄桃花红梨花白的春天美景。游客穿行于梨花园中。素净淡雅的梨花绽放枝头。千树梨花白似雪。千树梨花白。梨园美景惹梨花开了!赤壁市余家桥乡百亩梨花绽放如雪似雾迎春湖北日报客户端讯(通讯员余琎)又是一年梨花开放时。赤壁市余家桥乡丛林村200多亩梨花竞相开放。进入梨园,一簇簇雪白的梨花,如团团云絮,漫卷轻飘。走近观赏,只见梨花白如皓雪,在那嫩黄安徽一地文旅局长仙气飘飘为家乡山水代言!受访时称有压力但更希望家乡能火大皖新闻讯古来时间之美诉于你听,山乡石台,秋浦长歌。石台县文旅局局长刘海燕申请出战!石台山水,分秒皆是诗意最近几天,池州市石台县文化和旅游局局长刘海燕仙气飘飘地加入卷流为当地旅游出荔湾桥中街这条路宫粉紫荆热烈绽放,街坊拍照打卡好去处!三月,正是踏春赏花的好时节近日位于桥中街道桥中中路一侧的宫粉紫荆开了!有不少路人前往拍照打卡哦小e在现场看到成排的宫粉紫荆沿着沙坦涌竞相绽放,延绵数里,粉紫色的花朵压满枝头,在蓝天重庆创建国家级卫星互联网产业创新中心两江新区成主阵地21世纪经济报道记者文静重庆报道去年12月,被誉为中国复眼的4部16米孔径雷达在重庆两江新区明月山上,成功拍摄了我国首幅月球环形山地基三维雷达图像,拓展着人类深空观测的边界。5年前
你凭什么说感觉没有年味?今天看了篇小文,说没有年味绝对和七天拼假有关系,只看标题,我不需要看内容,就觉得有些人看问题总喜欢在外部找原因,却从不检讨自身的硬伤我记得刚参加工作那会,春节四天假,没有年味了吗?热血铸忠诚公安楷模向人民报告人民视觉视觉中国供图制图李晗整理何春中制图李晗贺丽远,工具箱!贺丽远缓慢地靠近师傅,却发现自己的手,抖得连工具箱都打不开。当天,炸弹被顺利拆除。在最终认定这是一枚假炸弹后,贺丽远久性教育到底有没有必要普及?建议提前了解关于性教育很多人都会羞于表达。其实关于性教育这个问题很多情商高的父母,他们会提前和孩子讲清楚,认为这是孩子成长道路上必须要经历的一个问题,如果早期和孩子讲清楚了这个问题,那么在发生成绩好的孩子是抑郁症高危人群?正念研究这项能力帮助孩子一生大多数父母,都希望孩子能够拥有最美好的一生健康的身心富足的生活受人尊敬的社会地位良好的人际关系等等。然而许多父母却不知道如何才能帮助孩子实现这样的人生,家长们通常只能用最直观的可衡美国研究幼童误食大麻数量激增,超50仅2到3岁,因其包装与零食相似美国最新的一项研究显示,儿童误食大麻数量飞速增长,因为一些含有大麻的食品包装与零食相似,导致儿童容易误食。据商业内幕报道,根据美国伊利诺伊州三位急救专家于3日发表的一项研究,201云享健康是什么正在伤害孩子的眼睛?聚焦生活,专注健康,每个人都是自己健康第一责任人轻松幽默,洞察错误生活方式通俗易懂,科普正确疾病预防日常食材,烹出健康美味人生普及健康知识,提升健康素养,增进全民健康在全民打响近视嘉堡护理五个方面教你如何找月嫂?如今家政行业蓬勃发展,但从业人员水平良莠不齐。选一位合适的月嫂犹如大海捞针,选对人很重要。合适的月嫂能给您贴心的服务,一流的体验,帮助您科学带娃那么,面试月嫂需要了解她们哪方面信息孩子吃手指到底能不能阻止?孩子吃手指是否卫生?孩子吃手指到底能不能阻止?孩子吃手指是否卫生?孩子吃手指好吗?为什么孩子喜欢吃手指?弗洛伊德性心理发展阶段之口欲期口欲期简单来说就是孩子通过吸吮手指来刺激皮肤获得快感。当孩子吸吮手揪心!熊孩子捣鼓电动车手被电黑儿童安全意识淡薄一不留神就会出现意想不到的危险!近日安徽蚌埠一名男孩在院内玩耍因好奇心作祟将硬币塞进了电动车充电口只听嘭的一声一串火花冒出,吓坏了孩子孩子妈妈表示当时自己正在屋内听家庭教育孩子的梦想如非你所愿,你将如何以待?大家好,我是Maco。本文来源于微信公众号美可玩故事服务号最近有一个妈妈来找江老师咨询她说,她跟孩子大吵了一架,原因是孩子很喜欢画漫画,在家画了很多的漫画。而她本身是不喜欢漫画的,孩子出现这些情况要及时就诊!图片抱着侥幸心理一直在家硬扛,没想到扛出这么重的病!12岁的周周(化名)的家长后悔不已。之前因为不太重视,加上怕去医院,12岁男孩咳嗽一周不就医,结果再来到医院时检查发现,一侧肺部
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网