漫谈文件系统

Wikipedia对文件系统定义:

In computing, a file system or filesystem is used to control how data is stored and retrieved.

翻译成中文大致意思:文件系统主要是管理数据存储以及数据如何检索的,而数据存储在磁盘或内存中。上期我们聊过了漫谈虚拟内存,本期我们就重点介绍磁盘中的机械磁盘的组成以及工作原理,然后引申到文件系统。

机械磁盘

机械磁盘由磁头(head)、磁道(track)、柱面(cylinder)、扇区(sector)和盘片(platter)组成。其中,磁头悬浮在盘片上,并且每张盘片上下各有一个磁头;每张盘片的磁道数是相同的,每张盘片相同位置的磁道组成柱面;而每一个磁道由数量相同的扇区组成,我们知道离主轴越远的扇区面积越大,而扇区大小一般为512B,必然导致存储密度越低,这样做明显浪费空间,为了解决问题,我们将磁盘密度改为等密度结构,这就意味着外围磁道的扇区数量要大于内圈的数量。

  • 物理图
  • 逻辑图
  • 数据读取流程 假设目标扇区和当前磁头位置不在同一个磁道上,首先,磁头从一个磁道移动到另一个磁道,同时,盘片也在旋转,此时,虽然磁头到达了该磁道,但是还没有到达目标扇区,因此还需要等待,最后读取红色区域。

文件

基于上述介绍的机械磁盘,我们如何访问磁盘扇区?通过访问(柱面,磁头,扇区)确定一个扇区,但是用户是无法直接访问扇区的,操作系统将扇区抽象成文件! 因此,文件是我们操作操作系统最小的单位。

文件系统设计

文件系统采用分层设计,最底层的是设备,接着是IO控制(设备驱动),基本文件系统(向设备驱动程序发出命令),文件组织模块(负责文件的逻辑块和物理块,以及管理空闲空间),逻辑文件系统(管理元数据)

文件系统的实现

文件系统的实现包括磁盘结构和内存结构,即我们将文件以什么结构存储于磁盘,以什么结构存储于内存。

磁盘结构

这里以Linux中的Ext2的磁盘结构为例,需要注意的是我们需要对硬盘进行格式化生成如下图所示的磁盘结构。其中,主引导扇区(0柱面、0磁头、1扇区,大小为512B)由MBR(Main Boot Record,主引导记录,大小为446B)和各个分区组成。MBR又包含位于磁盘最前边的一段引导代码即Boot Loader磁盘分区表魔数。磁盘分区表记录的是分区信息,魔数指定哪个分区为活动分区,也就是说把控制权交给这个活动分区的操作系统。需要注意的是图中我只化了2个分区,而在实际情况下我们最多可以化4个分区,这里说明一下为什么最多只能化4个分区,我们知道一个扇区的大小是512B,其中主MBR就占用了446B,结束标志占用2B,所以分区表的大小就只有64B,而每个分区信息用16B表示,因此硬盘只能划分为4个主分区。

由于每个分区都可以安装操作系统,因此每个分区中都有引导块,引导块是包含引导操作系统所需要的信息。由于分区容量很大,因此,我们会将分区进一步划分为各个块组,块组包含超级块、块组描述、磁盘块位图、inode位图、inode表以及数据块,其中,超级块(superblock)描述的是整个分区的详细信息,如分区的块数、块的大小、空闲块的数量和指针、空闲FCB的数量和指针,需要注意的是同一个分区中的块组中的超级块信息是一样的,只有块组0 的超级块会被加载到内存,而且由于每个块组都保留超级块信息,保证了磁盘高可用;块组描述记录inode表的起始位置、数据块的起始位置、空闲inode表和空闲数据块;磁盘块位图管理的是空闲磁盘块;inode位图管理空闲的inode;inode表存放inode信息。

内存结构

我们每次打开一个文件,即open 文件,需要发起操作系统调用,系统调用会查看一个表:系统范围打开的文件表,每个进程会维护打开的文件表,索引号指向的是系统范围打开的文件表,这个索引号在Linux上称为文件描述符,在windows上称为文件句柄。

文件存储

连续存储
  • 顺序访问速度快,随机访问速度也快,例如:访问Hello.java,磁头定位到编号为1的磁盘块,接着顺序读取编号为2、3磁盘块。但是,容易出现碎片
  • 注意:图中的每一块表示逻辑块
链式存储
  • 增、删内容很快;
  • 顺序访问速度还好,但是随机访问速度很慢。
折中方案 - 索引存储

由于连续存储和链式存储都存在一些缺点,因此我们的先辈们想出了一个折中方案即索引存储。首先有一个磁盘块(索引节点)不存实际数据,它存放的是元数据和这些数据应该存放在哪些磁盘块的信息。例如下图中的索引节点20,它存放的元数据包含权限、所有者和时间戳,数据信息包含磁盘1、3、12、13、19。

  • 优点:顺序访问和随机访问速度很快
  • 缺点:需要一个额外的空间,即索引节点存储了大量的信息。

通过一个索引节点是不是可以解决所有问题呢?由于一个节点的大小是有限的,当出现一个特别大的文件,一个索引节点不放不了这么多磁盘块信息,那应该怎么办?我们将索引节点划分为若干个区域,元数据区域保持不变,磁盘索引区域划分为直接块间接块,直接块表示通过索引直接找到数据块,间接块表示索引指向的是另一个索引节点。

以查找/tmp/Test.log为例,首先获取根目录/的inode号,一般情况下根目录的inode号是固定的,假设为1,通过inode号找到根目录属性和它的磁盘块,然后从硬盘中读取第405磁盘块,该磁盘块内容中包含tmp的inode号,以此类推,最终找到Test.log的磁盘块。


欢迎关注微信公众号:木可大大,所有文章都将同步在公众号上。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏编程

年底总结一下Python WEB最好用的几个框架,让你有一个系统的了解

2017年就要过完了,我们来总结一下2017年最好用的17个Python Web框架 群内不定时分享干货,包括2017最新的python企业案例学习资料和零基础...

8668
来自专栏程序员的碎碎念

如何解决Python包依赖问题

以简洁高效(指编程较为高效, 而不是运行速度)出名的Python, 在包依赖问题上有时候让人挠头.

1952
来自专栏IT技术精选文摘

解Bug之路-记一次JVM堆外内存泄露Bug的查找

1433
来自专栏MYSQL轻松学

Mysql Group Replication介绍

一、Mysql Group Replication简介 Mysql Group Replication(MGR)是一个全新的高可用和高扩展的MySQL集群服务...

6924
来自专栏Java架构

今咱们来聊聊JVM 堆外内存泄露的BUG是如何查找的前言内存泄露Bug现场查找线索总结

3374
来自专栏企鹅号快讯

Python的开端

今天就说说Python的安装和它的开发环境,我安装的是Python3.5.2,也有很多人用的Python2.7,这两个版本有些地方都变了,但是差异可以学了Pyt...

2146
来自专栏吴伟祥

Linux Partition scheme 分区方案(一)

根分区包含Linux系统所有的目录。如果在安装系统时只分配了/分区,那么上面的/boot、/usr和/var将都包含在根分区中,也就是这些分区将占用根分区的空间...

2752
来自专栏Java架构

今咱们来聊聊JVM 堆外内存泄露的BUG是如何查找的

JVM的堆外内存泄露的定位一直是个比较棘手的问题。此次的Bug查找从堆内内存的泄露反推出堆外内存,同时对物理内存的使用做了定量的分析,从而实锤了Bug的源头。笔...

1.2K17
来自专栏Android 开发者

非 SDK 接口常见问题 | Android 开发者 FAQ Vol.13

4263
来自专栏软件测试经验与教训

看图说话:持久式XSS(跨站)漏洞示例

读书与实践是获取知识的主要渠道,学习的权力只掌握在每个人自己手中,让学习成为一种生活的习惯,这比任何名牌大学的校徽重要得多!

2512

扫码关注云+社区

领取腾讯云代金券