• 进入"运维那点事"后,希望您第一件事就是阅读“关于”栏目,仔细阅读“关于Ctrl+c问题”,不希望误会!

Linux中特种文件系统介绍

系统管理 彭东稳 9年前 (2015-08-25) 28573次浏览 已收录 0个评论

一、日志文件系统

在RedHat系统发行版中,Redhat 5.0使用的文件系统是Ext3,而在Redhat 6.0中使用的是EXT4,到了Redhat 7.0中没有在使用EXT系列文件系统了,而是使用了XFS文件系统。这些所有的文件系统都属于日志型文件系统(EXT2就不是日志型文件系统),既然是日志型文件系统那么下面就来说说日志。

  • 理解日志

1)元数据

元数据就是诠释数据的数据,意思就是作为文件系统,一定要提供存储、查询和处理数据的功能。那么文件系统就保存了一个内出数据结构,使得这些操作成为可能。这个内出数据结构就是元数据,它为文件系统提供特定的身份和性能特征。

对于用户来说不用关心元数据,因为元数据是专门交给文件系统的驱动程序使用的,但是要想文件系统的驱动程序好好干活,它就得轻松愉快地找到元数据,要求有三:一要合理、而要一致、三要无干扰。否则的话,驱动程序就没法理解元数据,也操作不了,另外说一点文件系统是文件系统,文件系统驱动是文件系统驱动,不是一回事。

2)fsck

fsck我们知道是用来检查和修复文件系统的,每次Linux启动,在没有挂载任何文件系统的时候,都会启动fsck扫描一下/etc/fstab文件中列出的所有本地文件系统;每次Linux关闭,它都把还在内存中的被称之为页面缓存或磁盘缓存中的数据转送到磁盘,还要保证把已经挂载的文件系统卸载干净。简单了就是:fsck要检查哪些即将被挂载的文件系统,之前是被卸载干净了的,然后做出一个合理的架设,所有元数据都是干净的。

以上是一般正常情况;但是当Linux遇到异常关机,重启后fsck就会发现有文件系统没卸载干净,对应的元数据肯那个不干净,已经出了问题。于是乎开始分离苦干,全面审查元数据,修正一切可以修复的错误,文件系统又可以正常使用了。

3)日志

文件系统的日志记录了它对元数据都做了些什么操作,元数据出现问题后,fsck在遇到有日志的文件系统时要做的事情就是放行,接下来由文件系统驱动负责按照日志里面的记载去恢复元数据,恢复方法其实跟fsck类似,不过时间上可就快很多了,使用日志文件系统修复上百GB的元数据也只是一眨眼时间(当然日志只是解决修复时间的问题,跟数据丢失没有关系不要混淆)

说完日志,接下来说说ReiserFSEXT4XFS这几款文件系统。

  • ReiserFS

ReiseFS属于日志型文件系统,它的设计者Hans Reiser想法是设计一个最好的文件系统,不单能够管理好用户的文件,还能够使用环境干点别的,比如代替数据库。

那么怎么才能让文件系统能够适应环境呢?ReiserFS就干了这么一件事儿,关注小文件性能。因为我们常见的如ext2ext3等文件系统一遇到过多小文件就傻了。就拿EXT2来说,它比较擅长的是存储大量大小在20k以上的文件,但是你要让它帮你存储2000020字节做左右的文件,ext2hold不住了。不但性能急剧下降,存储效率也是急剧下降。因为ext2的最小存储单元式1k4k,即便你只存储1个字节,也得占用1k4k(默认是4k)一个数据块,这样换算下来,20000乘以4k等于80M,而你实际需要的只有20000乘以50字节等于1M,存储效率只有5%

ReiserFS处理小文件的性能好得不得了,处理小于4k的文件时,比ext2815倍。而且处理大于4k的文件时性能也不会有什么损失。ReiserFS 采用了B*树的数据结构。这是一种全新的经过特殊优化的树形数据结构。ReiserFS用它来组织元数据,相当于整个磁盘分区是一个B*树。

B*树是什么呢?一般学计算机的都会接触点数据结构这个东西,链表、堆栈、树、图这些。作为“树”这种数据结构,听得最多的就是二叉树,单凡涉及二叉树,说得最多的就是二分查找,因为效率高(100万个数据,只要20几次比较就能找到所要的数据)。在二分查找领域中,普遍有二叉查找树、平衡二叉查找树,AVL树和红黑树。红黑树都是用在内存查找这种介质中,而用在磁盘介质中使用的算法是B+树,B+树是B树的变形,在降低磁盘读写代价的同时,提高了查询效率的稳定性。而B*树就是B+树的变形,B*树分配新节点的概率比B+树要低,空间利用率更高。

利用B*树的特性,ReiserFS允许一个目录下可以容纳10万个子目录,还可以根据需要动态的分配索引,这样也就省去了固定索引,没有附加空间。提高了存储效率。ReiserFS的与总部同之处还有,不适用固定大小的数据块分配存储空间靠此阿勇精确分配原则,这样就不会有磁盘空间的浪费。而且ReiserFS还提供了一种叫以尾文件为中心的特殊优化。什么事尾文件呢?就是比系统文件块小的文件或文件的结尾部分。为了提高性能,ReiserFS可以用力B*树的叶节点存储文件。从而不用把数据先保存在其他地方,然后在指向它。

ReiserFS虽然很不错,但是未来渺茫。2008428日,主创hans reiser被加州福尼亚州奥克兰法庭认定其杀妻罪名成立,判决15年监禁。从此ReiserFS的开发就基本处于停滞状态。就连曾大力推广ReiserFSNovell公司都开始反水,但是不管怎么样ReiserFS依然是Linux系统中最优秀的文件系统之一,而且现在依然是可以使用的。

  • EXT4

EXT(extended filesystem)系列的文件系统一直是红帽7.0系统发行版前使用的的文件系统,而EXT4是最新版本的的日志型文件系统。其特点如下:

1. 支持更大的文件系统和文件,文件系统容量可以达到1EB,而文件容量则达到16TB,这是一个非常大的数字了。对于一般的服务器而言,这可能并不重要但是对于大型磁盘阵列的用户而言,这就非常重要了。

2. Ext3文件系统只支持32000个子目录,而ext4理论上支持无限数量的子目录。

3. 增加了日志校验功能,日志是文件系统最常用的结构,日志也很容易损坏,而从损坏的日志中恢复数据会导致更多的数据损坏。增加日志校验功能后可以很方便地判断日志数据是否损坏。并且也支持“无日志”模式,可以选择是否开始日志,因为日志总归会占用一些开销。

4. 支持在线碎片整理、支持快速fsck、支持纳秒级时间戳等等。

二、特种文件系统

在Linux中除了上面说的一些经常接触的日志或非日志文件系统外,还有一些特别的文件系统,如:procfs、tmpfs、devfs、sysfs等等。在我们的根目录下有这样一些目录/proc、/sys,这些目录中在系统启动前什么东西都没有,而是用来存放系统启动中的信息。使用mount命令可以看到这两个目录使用的文件系统,如下:

除了一些我们熟知的正常文件挂载之外,还有我们上面所说的一些特种文件系统。这些文件系统在Linux整个系统运转中非常重要的。

ProcfS

procfs是进程文件系统的缩写,这是一个伪文件系统(启动时动态生成的文件系统),用于用户控件通过内核访问进程信息。但是经过不断的演进,如今Linux提供的procfs已经不单单拥有访问进程信息,还是一个用户控件与内核空间交换数据修改系统行为的接口。这个文件系认通常被挂载到/proc目录下。procfs并不是Linux的原创,它源自于UNIX世界,可能是历史太过悠久,臃肿,如今好多人开始讨厌他,Linux已经开始引入devfssysfs了。

如今的/proc目录变得很复杂很复杂了,这也是开始排挤它的出发点。大多数情况下,你在/proc目录下能够看到的文件差不多就是以下这些,它们都是只读的,不能用于修改,仅用于获得系统中进程的运行信息。典型的工具就是top、ps等,就是依据目录中的文件所提供的内容进行工作的。

apm:高级电源管理信息。

buddyinfo:buddy算法内存分配信息。

locks:内存锁。

meminfo:存储信息。

cpuinfo:CPU信息。

filesystem:支持的文件系统。

partions:显示识别的磁盘分区。

dma:使用的DMA通道。

modules:系统已经加载的模块文本列表。

diskstats:磁盘I/O统计信息。

interrupt:中断的使用情况,记录中断产生的次数。

pci:内核识别的PCI设备列表。

vmstat:虚拟内存统计表。

zoneinfo:内存管理区信息。

version:内核版本。

uptime:系统正常运行时间。

interrupts:中断信息,可以看到网卡中断信息都发给哪个CPU了,默认都是发给CPU0,所以可以利用这个让专门的CPU处理专门的中端以提高系统性能。

[number]:这是每一个进程的目录,目录名就是进程ID。里面包含了一些文件,这些文件描述着一个进程的方方面面,这也是procfs最初的体现。

……

这里还有一个特别的目录,就是sys目录。它所包含的文件大多是可以写的,通过改写这些文件的内容,可以起到修改内核参数的目的。实际上系统命令sysctl就是利用这个目录实现的全部功能。使用C语言编写时,系统调用ysctl是这个接口的封装。

Tmpfs

在tmpfs出现之前,人们使用Ramdisk。RamDisk就是将一部分固定大小的内存当做分区来使用,相对于传统的硬盘文件访问来说,这可以极大地提高在其上运行的文件访问速度。当然RamDisk也是一种非常古老的技术。

虽然RamDisk是一种能够加速文件的速度,但是会占用物理内存,并且一旦断电信息就会丢失。Ramdisk还有一个缺点就是你设定的Ramdisk有多大它就需要占用多大的物理内存,哪怕里面一个字节的数据也没有。虽然这个时候的内存已经没有那么贵了,但是还是比硬盘要贵很多的。所以这种方式必须要改进,应该更高效地利用内存。另外,在不断的实践中,人们发现,大量的临时文件其实很影响程序的性能。于是开始有人把程序产生的临时文件放入Ramdisk中来提高整体性能。其实还是拿web服务器来说,大量的缓存文件就可以看作一种临时文件,因为临时文件有一个特性就是它是临时的。即便丢了,也无大碍。

鉴于上述的一些需求,在Linux 2.4内核中,引入了一个全新的文件系统—–tmpfs

tmpfs类似与Ramdisk,它既可以使用内存,也可以使用交换分区。tmpfs文件系统使用虚拟内存子系统的页面来存储文件,tmpfs自己不需要知道这些页面实在物理内存中还是在交换分区中,一切由虚拟内存说的算。所以,tmpfs跟普通的用户进程差不多,使用的只是某种形式的虚拟内存。tmpfs跟普通的文件系统不同,普通文件系统在Linux中都被称为块设备。而tmpfs是直接建立在虚拟内存之上的,使用一个简单那的mount命令就可以创建tmpfs文件系统了。不需要什么格式化。

另外tmpfs刚开始被挂接时只有很小的空间,但是随着文件的复制和创建,tmpfs文件系统驱动程序会分配更多的虚拟内存。并按照需求动态地增加文件系统的空间。当有文件系统被删除时,tmpfs文件系统驱动程序会动态地减少文件系统释放虚拟内存资源。做到循环利用,按需分配。

tmpfs虽然是基于虚拟内存,但是它还是内存,所以速度上非常快,读写几乎是瞬间完成。即使使用了交换分区,性能仍是卓越的。只要虚拟内存比较空闲一部分tmpfs的文件就会被移动到物理内存中去。而且不常用的文件,也会被自动交换出去。腾出更多地方给用户进程。显然tmpfs是遵循虚拟内存的调度策略。tmpfs是一个基于内存的文件系统,所以不要指望它能提供持久存储。、

使用tmpfs

要使用tmpfs最基本的就是要把它挂在到文件系统的某个节点上,只需要使用以下命令即可:

这个时候/tmp目录就开始使用tmpfs文件系统了,所有使用/tmp目录作为临时目录的程序都会得到很好的速度提升。但是这里也会有一个问题就是会用光虚拟内存,这个时候会出现什么后果呢?在Linux内核2.4之前没有内存可用了是直接宕机,在2.6内核开始内建了一个最后一道防线,用来在没有内存可用的情况下会选择使用内存最多的一个进程干掉从而来释放内存。但是由于tmpfs是内核的一部分并不是用户进程,所以内核只能选择一个替罪羊干掉。对于内核来说也没有什么更好的办法了。

其实tmpfs的设计者们早就想到了这个问题,于是提供了一个参数,让你来设定tmpfs的最大占用量,可以使用如下命令:

我们在使用mount命令时,看到tmpfs挂载到了/dev/shm上,也就是这个tmpfs on /dev/shm type tmpfs (rw,rootcontext=”system_u:object_r:tmpfs_t:s0″)这个又是什么鬼呢?

这里解释一下,/dev/shm目录就是大多数发行版提供的一个默认的tmpfs文件系统,这是POSIX标准所规定,因为POSIX标准的共享内存就是利用tmpfs所实现的。不过目前大家常用的还是System V的共享内存,POSIX的共享内存不是很流行。既然/dev/shm就是现场的tmpfs,那么就在它下面创建一个新的tmp目录。注意要修改权限使得所有用户都能访问,因为这是业界针对/tmp的强制规范。最后使用绑定挂载,将/dev/shm/tmp这个tmpfs绑定挂载到/tmp上,这样所有使用/tmp目录作为临时文件的程序都会受益于tmpfs所提供的超高性能。另外,这样还有另外一个好处就是,/dev/shm是由发行商所提供的标准tmpfs,它的最大容量限制一般可以被认为是最为优秀的,直接拿来用总比自己手动分析要容易的多。

绑定挂载的命令如下:

Devfs

Devfs也叫设备文件系统(Device Filesystem),设计它的唯一目的就是提供一个新的(更理性的)方式管理通常位于/dev 的所有块设备和字符设备。您也许知道,典型的/dev 树包含数百个块特殊文件和字符特殊文件,它们全都在根文件系统上。每个特殊文件都可以让用户空间进程轻松地与内核设备实现交互。举例来说,通过对这些特殊文件执行操作,您的X服务器就能够访问视频硬件,fsck可以执行文件系统检验,lpd可以通过并行端口向打印机发送数据。

然而,虽然设备特殊文件本身是一件好事情,但典型的Linux系统以一种不太理想而且麻烦的方式管理这些特殊文件。如今,Linux支持很多不同种类的硬件。

这意味着在/dev下的文件数量也越来越多,数以千记绝不过分。只是这还不是问题的根本,最根本的是这些文件都是写死的,而且大多数根本不会映射到系统中,因为再复制的服务器,撑死也就配备几十个设备。显然是使用99%的努力,只是为了解决那1%的问题。况且谁也不知道用户以后添置什么新的设备。所以这些文件一个都不能动。

devfs的诞生,虽然对上面的问题做了一定的处理,但是有些不是很合理。但是它解决了一个更要命的问题,那就是设备号的问题。传统的Linux设备驱动程序,要想系统提供一个文件映射,需要提供一个主设备号。而且这个设备号必须保证其唯一性,由于历史的原因,早些年内存太贵,所以这个设备号被设计的只有8位。显然这是稀缺资源,既然这样,驱动开发人员自然不能凭空捏造一个主设备号,只能向Linux内核开发人员去申请,这就比较麻烦了。

那么devfs是怎么解决这个问题的呢?它给驱动开发人员提供一个叫devfs_register()的内核API,这个API可以接受一个设备名作为参数。调用成功后,在/dev目录下就会出现与设备名相同的文件名。而且devfs_register()仍然支持主设备号的策略。这样可以保持向下兼容性。降低早起设备驱动程序移植的复杂性。一旦所有设备程序启动并向内核注册适当的设备,内核就启动/sbin/init进程。系统初始化脚本开始执行,再启动过程初期,rc脚本将devfs文件系统安装在/dev中。这样/dev中就包含了devfs所表达的所有设备映射关系。所有注册的设备依然可以通过/dev目录进行访问,用户应用程序不用做任何修改。这种设计最大的优点就是:所有需要的设备映射关系都由系统自动创建,因此也就不用写死设备文件了,那么/dev目录下就不会充斥着大量的无用的设备文件了。在实际应用中,只要查看一下devfs,就能够知道这个系统上有什么设备了。

devfs让一切变得容易了许多,最典型的就是当你编写一个显示实时系统信息的程序时,不用做依次轮询哪些设备是“活跃的”这样费时的工作。因为只要读取/dev下的所有信息就可以搞定。即便用户只想查看某一个类型的信息,比如光驱,根据devfs的约定,只需要读取/dev/cdroms下的文件即可。在实际操作中,比如你想访问一个特定的块设备,还有很多不同的途径。例如:一个服务器上,只有一个SCSI光驱;使用devfs后,就可以通过/dev/chroms/cdrom0访问;还可以通过/dev/scsi/host0/bus0/target4/lun0/cd访问它。这两种都映射了同一个设备。还可以通过一种更老式的设别名称/dev/sr0访问光驱,这都是因为有一个非常便捷的叫devfs的小程序在幕后完成的工作。

Sysfs

sysfs是后来的,使用另外一个种设备udev干掉了devfs,并且公开了devfs四宗罪:

第一,不确定的设备映射,有时一个设备映射的设备文件可能不同,例如我的U盘,可能对应sda也可能对应sdb。

第二,没有足够的主/次设备号,当设备过多的时候,这就是一个问题。前面说过虽然devfs以及意识到将来会有很多设备,但是还是没有处理好。没有给主/次设备号留太多的扩展空间。

第三,dev目录下文件太多而且不能表示当前系统上的实际设备。

第四,命令不够灵活,不能任意指定。

虽然有些是欲加之罪,但是Linux是一个崇尚简单的世界,只要有一条能够说明你很麻烦,就有理由干掉你。于是devfs死掉了,sysfs来了。
sysfs是Linux 2.6所提供的一种虚拟文件系统。这个文件系统不仅可以把装置(devices)和驱动程式(drivers)的资讯从kernel space输出到user space,也可以用来对装置和驱动程式做设定。sysfs的目的是把一些原本在procfs中的关于装置的部份独立出来,以[装置阶层架构}(device tree)的形式呈现。这个档案系统由Patrick Mochel所写,稍后Maneesh Soni撰写 “sysfs backing store path”,以降低在大型系统中对内存的需求量。

sysfs一开始以ramfs为基础,也是一个只存在于内存中的档案系统。ramfs是在2.4核心处于稳定阶段时加入的。ramfs是一个优雅的实做,证明了要在当时仍很新的虚拟档案系统(VFS)下写一个简单的档案系统是多么容易的一件事。由于ramfs的简洁以及使用了VFS,稍后的一些内存形式的档案系统都以它作为开发基础。

sysfs刚开始被命名成ddfs(Device Driver Filesystem),当初只是为了要对新的驱动程式模型除错而开发出来的。它在除错时,会把装置架构(device tree)的资讯输出到procfs档案系统中。但在Linus Torvalds的急切督促下,ddfs被转型成一个以ramfs为基础的档案系统。在新的驱动程式模型被整合进 2.5.1 核心时,ddfs 被改名成driverfs,以更确切描述它的用途。在2.5核心开发的次年,新的‘驱动程式模型’和‘driverfs’证明了对核心中的其他子系统也有用处。kobjects被开发出来,作为核心物件的中央管理机制,而此时driverfs也被改名成sysfs。

正因为devfs上述这些问题的存在,在linux2.6内核以后,引入了一个新的文件系统sysfs,它挂载于/sys目录下,跟devfs一样它也是一个虚拟文件系统,也是用来对系统的设备进行管理的,它把实际连接到系统上的设备和总线组织成一个分级的文件,用户空间的程序同样可以利用这些信息以实现和内核的交互。该文件系统是当前系统上实际设备树的一个直观反应,它是通过kobject子系统来建立这个信息的,当一个kobject被创建的时候,对应的文件和目录也就被创建了,位于/sys下的相关目录下,既然每个设备在sysfs中都有唯一对应的目录,那么也就可以被用户空间读写了。用户空间的工具udev就是利用了sysfs提供的信息来实现所有devfs的功能的,但不同的是udev运行在用户空间中,相对更稳定安全和简单那;而devfs却运行在内核空间,而且udev不存在devfs那些先天的缺陷。很显然,sysfs将是未来发展的方向。内核的结构化设备模型在用户空间就称为sysfs.它与procfs类似,二者都位于内存的文件系统中,而且包含内核数据结构的信息。但是,procfs是查看内核内部的一个通用视窗,而sysfs则特定的对应于设备模型。因而,sysfs并非procfs的替代品。进程描述符、sysctl参数等信息属于procfs而非sysfs。udev的大多数功能都取决于sysfs。

Udev

udev是Linux kernel 2.6系列的设备管理器。它主要的功能是管理/dev目录底下的设备节点。它同时也是用来接替devfs及热插拔的功能,这意味着它要在添加/删除硬件时处理/dev目录以及所有用户空间的行为,包括加载固件时Linux 2.6.13内核。udev的最新版本依赖于升级后的的uevent接口的最新版本。使用新版本udev的系统不能在2.6.13以下版本启动,除非使用noudev参数来禁用udev并使用传统的/dev来进行设备读取。

一般当内核检测到在系统中出现了新设备之后,内核会在sysfs文件系统中为该设备生成一项新的记录,一般sysfs文件系统会被mount到/sys目录中。新纪录是以一个或者多个文件或者目录的方式来表示,每个文件都包含有特定的信息。udev在系统中是以守护进程的方式udevd在运行,它通过某种途径检测到新设备的出现,通过查找设备对应的sysfs中的记录得到设备的一些信息。udev会根据/etc/udev/udev.conf文件中的udev_rules指定的目录,逐个检查该目录下的文件,这个目录的文件都是针对某类或者某个设备应该施行什么措施的规则文件。udev读取文件是按照文件名的ASCII字母顺序来读取的,如果udev一旦找到了与新加入的设备匹配的规则,udev就会根据规则定义的措施对新设备进行配置。同时不再读后续的规则文件。

至于udev不管设备连接的顺序而维持一个统一的设备名,udev通过对内核产生的设备名增加别名的方式来达到上述目的的。udev是用户模式程序,不会更改内核的行为。因此,内核依然可以产生设备名比如sda、sdb等等。但是udev可以根据设备的其他信息,比如总线信息也就是bus、生产商也就是vendor等不同来区分不同的设备,并且产生设备文件。udev只要为这个设备文件取一个固定的文件名就可以解决这个问题。在后续对设备的操作中,只要引用新的设备名就可以了。但是为了保证最大限度的兼容,一般来说,新设备总是作为一个对内核自动产生的设备名的符号链接来使用的。


如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。
喜欢 (0)
[资助本站您就扫码 谢谢]
分享 (0)

您必须 登录 才能发表评论!