文件系统考古:1974-Unix V7 File System

news2024/11/29 0:55:41

有时,进步难以察觉,特别是当你正身处其中时。而对比新旧资料之间的差异,寻找那些推动变革的信息源,我们就可以清晰地看到进步的发生。在Linux(以及大部分Unix系统)中,都可以印证这一点。

Unix V7 是 Unix 操作系统的一个重要的早期版本,于 1979 年发布,是贝尔实验室最后一个广泛分发的版本。它是第一个真正可移植的 Unix 版本,被移植到了多种平台上,包括 DEC PDP-11, VAX, x86, Motorola 68000 等。Unix V7 的 VAX 移植版本,叫做 UNIX/32V,是流行的 4BSD 系列 Unix 系统的直接祖先。许多老牌的 Unix 用户认为 Unix V7 是 Unix 发展的顶峰。

Unix V7 Research Release 的源代码可以在 unix-history-repo 这个由 Diomidis Spinellis 维护的项目中找到。如果你想深入了解 Unix 的设计原理,可以参考 Maurice J. Bach 的经典著作 The Design of the Unix Operating System,并查看 Research V7 Snapshot 这个分支的代码库。

Machines

1974 年,计算机拥有一个“核心”,即中央处理单元。然而,在某些计算机中,这个“核心”已经发生了变化。不再是由多个部件(如算术逻辑单元、寄存器、顺序控制器和微码存储器)组成的设备,而是一颗单一的集成芯片,单个芯片上集成了数千个晶体管。它们被叫做“小型计算机”。

Kernels

在 Unix 中,我们通过配置头文件(header file)来处理系统资源。如下图所示,这里显示了头文件中配置的默认值,数据结构是数组,所示值是相应的数组大小。如果要更改它们,则需要编辑文件,重新编译和链接内核,然后重新启动系统。

它有一个文件系统缓冲区缓存(file system buffer cache),使用 NBUF(29)个磁盘块,每个磁盘块的大小是 512 字节,用来暂时存储磁盘上的数据块和 inode,从而加速文件系统访问。另外还有一个索引节点数组(inode array),它有 NINODE (200)个条目,每个条目对应一个文件的元数据,还可以同时挂载 NMOUNT (8)个文件系统。每个用户最多可以运行MAXUPRC(25)个进程,总共有 NPROC(150)个系统进程。每个进程最多可以打开 NOFILE(20)个文件。

阅读 Bach 的著作和 V7 源代码是很有趣的,尽管它们已经完全过时。因为这些源代码中呈现出的许多核心概念更加清晰,结构更简洁,有时甚至带有古老的风格。然而,正是这些概念定义了 Unix 文件系统。V7 Unix 被写入了 POSIX 标准,之后的每个文件系统都必须遵守它。如果您想了解更多相关示例,请参考 But Is It Atomic?

核心概念

Unix 文件系统的基本概念和结构来自这个系统。其中一些概念甚在现代系统中依然存在。

磁盘由一系列数据块(block)组成,从第 0 块开始,一直到第 n 块结束。在文件系统的开始部分,我们可以找到超级块(superblock)。它位于文件系统的第 1 块。超级块存储了文件系统的一些基本信息,比如文件系统的大小、空闲块的数量、空闲索引节点的数量等。当我们执行挂载(mount)系统调用时,系统会找到一个空闲的挂载结构(mount structure),并且从磁盘上读取超级块,把它作为挂载结构的一部分。

Inode

内存中的超级块(in-memory superblock)是磁盘上超级块的副本,用于加快文件系统的访问速度。它包含一个 short 类型的字段,用于存储一个索引节点数组(inode array)在磁盘上的位置。

索引节点(inode)是一个描述文件内容和属性的结构,文件内容由一系列数据块(block)组成,每个数据块的大小是固定的(通常是 512 字节或 1024 字节),文件属性包含文件名、大小、权限、时间戳等元数据(metadata)。

文件系统中的 inode 数组是一个 short 类型的计数器,它的最大值是 65535,也就是说文件系统中最多只能有 65535 个 inode。由于每个文件都需要一个 inode,因此每个文件系统最多只能容纳 65535 个文件。
每个文件具有一些固定属性:

  • (2字节)mode,它包含了文件的类型和访问权限;
  • (2字节)nlink,它表示这个文件有多少个名字;
  • (2字节)uid,文件的所有者;
  • (2字节)gid,文件所有者的组 ID;
  • (4字节)size,文件的长度,以字节为单位(定义为 off_t,长整型);
  • (40字节)addr 数组,包含了文件的数据块在磁盘上的地址;
  • (3x 4字节)三个时间,atime(访问时间),mtime(修改时间)和 ctime(所谓的创建时间,但实际上是最后一个 inode 更改的时间)。

总大小为 64 字节。

bmap()

Addr 数组包含 40 个字节,但它存储了 13 个磁盘块地址,每个地址使用 3 个字节。这对于 24 位来说非常适用,或者说对应于 16 个大小为 512 字节的兆块,总文件系统大小为 8M 千字节,即 8GB。

PDP-11 RL02K磁盘盒可容纳 10.4 MB,而更新的 RA92 可存储 1.5 GB。
Addr 数组在 bmap() 函数中被使用。该函数接收一个 inode(ip)和一个逻辑块号 bn,并返回一个物理块号。也就是说,它将文件中的一个块映射到磁盘上的一个块,因此得名。

前 10 个块指针直接存储在 inode 中。例如,要访问块 0,bmap() 将在 inode 中查找 di_addr[0] 并返回该块号。

额外的块存储在一个间接块中,而间接块则存储在 inode 中。对于更大的文件,会分配一个双间接块,并指向更多的间接块,最终非常大的文件需要甚至三次间接块。

代码首先确定需要多少层间接寻址,也就是要通过多少个间接块才能找到文件内容的磁盘块。然后,获取相应的间接块。最后,代码按照适当的次数解析间接寻址,也就是根据层数依次从间接块中读取其他间接块或直接块的地址,直到找到文件内容的磁盘块。

对于越来越大的文件,原始的 Unix 文件结构采用了逐渐增加的间接访问次数。这样形成了一个压缩的数组,其中较短的文件可以直接通过 inode 中的数据进行访问,而较大的文件则需要通过越来越多的间接访问来获取数据。为了提高性能,保持间接块在文件系统缓冲区高速缓存中是至关重要的。

这种扩展性取决于块大小(早期为 512 字节,现在为 4096 字节)和块号的字节大小(最初为 3 字节,后来为 4 字节甚至 8 字节)。

Atomic writes

文件的写入是在加锁的状态下进行的,因此它们始终具有原子性。即使是跨越多个数据块的写入操作,也是如此。这一点在 But Is It Atomic? 中有详细讨论。
这也意味着即使有多个写入进程,在单个文件上,任何时刻只能有一个磁盘写入操作处于活跃状态。这对数据库系统的开发者来说非常不便利。

Naming files

目录是一个具有特殊类型和固定记录结构的文件。

一个目录条目包含一个inode号(一个无符号整数)和一个文件名,文件名的长度最多可以达到14个字节。这使得一个磁盘块可以容纳32个目录条目,而一个目录文件的直接块可以引用的10个磁盘块可以容纳320个目录条目。

下层(lower)的文件系统中充满了大量的文件。这些文件没有名称,只有编号。
上层 (upper)的文件系统使用一种特殊类型的文件,具有简单的16字节记录结构,用于为文件分配最多14个字符的名称。一个特殊的函数namei()将文件名转换为inode号。

传递给namei()的路径名具有层次结构:它们可以包含/作为路径分隔符,并以\0(NUL)作为终止符。路径名若以/开头,则遍历将从文件系统的根目录开始,形成绝对路径名;若不以/开头,则遍历将从u.u_cdir,即当前目录开始。
该函数逐个消耗路径名的各个组成部分,使用当前活动目录,并在该目录中线性搜索当前组件的名称。当找到最后一个路径名组件或在任何阶段找不到组件时,该函数结束。如果在路径中的任何目录的任何点上,我们没有 x 权限,它也会结束。

该函数按顺序逐个处理路径名的各个组成部分。它使用当前目录,并在该目录中线性搜索当前组成部分的名称。函数的结束条件有两种情况:一是找到了路径名的最后一个组成部分,二是在路径的任何目录中,出现了无法访问的情况。
挂载点是特殊条目,它会从当前节点和文件系统的目录条目切换到挂载文件系统的根inode。这使得Unix中的所有文件系统看起来像是一棵单一的树,如果要进行"硬盘修改"的操作,只需简单地切换到不同的目录。

最终,该函数将返回给定路径名的inode指针,根据需要和需求创建(或删除)inode(和目录条目)。它是目录遍历和访问权限检查的集中点。

一些创新的想法以及限制

这个早期的Unix文件系统具有许多很好的特性

  • 它将多个文件系统呈现为一个统一的树形结构;

  • 文件是无结构的字节数组;

  • 这些数组以可动态增加深度的动态数组的形式存储。它们内部使用一种逐渐嵌套的间接块系统,其中数组的元素可以是指向其他数组或数据的指针,从而形成层次嵌套的结构。这使得磁盘搜索的复杂度为O(1);

  • 下层文件系统创建文件和上层的文件系统组织文件互相隔离,分工明确。获取inode的唯一方式是路径名遍历,并且在此过程中始终检查权限;

  • 文件名中只有很少的特殊字符,即/和\0(空字符)。

但也有明显的限制

  • 文件只能有16M个块;

  • 文件系统只能有非常有限的65535个inode。

还有一些令人讨厌的限制

  • 文件只能有一个正在写入的进程,这会导致并发性受限;

  • 目录查找是线性扫描,因此对于大型目录(超过320个条目),速度变得非常慢;

  • 没有强制文件锁定系统。但存在几种用于咨询式文件锁定的系统。

还有一些特殊情况

  • 在 Unix V7 系统中,没有 delete() 系统调用,而是 unlink() 系统调用,它可以删除一个文件的名字,并且那些没有任何文件名和打开文件句柄的文件会被自动清理。这会导致一些不符合预期的结果,例如,只有当一个完全没有文件名的文件被完全关闭时,它占用的磁盘空间才会被释放。许多 Unix 系统管理员都曾经问过他们的磁盘空间去哪了,当他们删除了 /var/log 目录下的日志文件,却忘记了有一些进程还在使用它;

  • 最初没有 mkdir() 和 rmdir() 系统调用,这导致了存在可被利用的竞态条件。竞态条件是指在多线程或多进程环境中,由于操作的顺序和时机不确定性,可能导致安全漏洞或错误行为的情况。这在 Unix 的后续版本中得到了修复;

  • 有一些操作在特定条件下具有原子性(例如write(2)系统调用),或者经过修改后具有原子性(mknod(2)和mkdir(2))。

在结构上,inode表和块和inode的空闲映射位于文件系统的开头,磁盘空间也是从磁盘的前端线性分配的。这导致了频繁的寻址操作,并且可能导致文件系统的碎片化(即文件存储在非相邻的块中)。

遍历目录结构意味着从磁盘开头读取目录的inode,然后向后移动到更远的数据块,再从磁盘开头读取下一个路径名组成部分的下一个inode,并向后移动到相应的数据块。这个过程在每个路径名组成部分上来回进行,速度并不快。

改进

在之后的发展中,minix文件系统忠实继承了PDP-11 V7 Unix文件系统,保留了它的特性包括局限。然而,随着时间的推移,在现代的Linux系统中,由于其不再具备实用性,它已经从内核源代码中移除。

在稍后的一篇文章中,我们将会了解到关于BSD快速文件系统,如何更好地布局磁盘上的数据,如何实现更长的文件名、更多的inode,以及如何通过考虑磁盘的物理特性来加快速度。

要解决目录查找时间线性增长、单个写入者或有限的文件元数据这些问题需要更新的文件系统。

翻译自:《50 years in filesystems》 由 KRISTIAN KÖHNTOPP 撰写。

如有帮助的话欢迎关注我们项目 Juicedata/JuiceFS 哟! (0ᴗ0✿)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/572651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

淘宝层级改版,五力模型上线!

最近临近618,淘系又各种功能改版,现在店铺层级也开始陆续改版了。从原来的只需要提升销售金额,到现在的五力模型。我们先说一下原来的店铺层级考核,跟现在的区别主要是哪? 1.原来店铺层级的考核升级特别简单&#xff0…

推荐一款神级编程工具[Cursor]自带gpt而且免费!

今天推荐一款非常好用开发工具,一个智能编程助手。 官网:https://www.cursor.so/ 适用平台:Mac、Windows、Linux。 助手的样子 可以做哪些事情? 编程语言:我可以回答关于各种编程语言(如Python、Java、Ja…

测试老鸟总结,从功能到自动化测试详细整理,测试之路广阔无垠...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 Python自动化测试&…

黑客零基础入门教程,从入门到精通学习路线规划,看完这篇就够了

很多人上来就说想学习黑客,但是连方向都没搞清楚就开始学习,最终也只是会无疾而终!黑客是一个大的概念,里面包含了许多方向,不同的方向需要学习的内容也不一样。 想要成为黑客,却苦于没有方向,…

戏曲APP软件开发需具备哪些功能呢?

戏曲是我国的国粹,传统戏曲文化源远流长,博大精深,数千年以来一直都是深受大众喜欢的文化生活的重要环节。随着时代的推进,娱乐形式更加多样化,传统的剧场演出形式的戏曲传播方式已经跟不上时代发展以及人们的需求了。…

python+Django+vue高校体育足球篮球联赛网站系统

系统主要是以后台管理员管理为主。管理员需要先登录系统然后才可以使用本系统,管理员可以对个人中心、用户管理、赛事信息管理、球队信息管理、球员信息管理、比赛分值板管理、系统管理等进行添加、查询、修改、删除,以保障足球联赛管理系统的正常运行。…

es elasticsearch 十 中文分词器ik分词器 Mysql 热更新词库

目录 中文分词器ik分词器 介绍 安装 使用分词器 Ik分词器配置文件 Mysql 热更新词库 中文分词器ik分词器 介绍 中文分词器按照中文进行分词,中文应用最广泛的是ik分词器 安装 官网下载对应版本zip 下载 放到 plugins 目录 新建 ik文件夹 考入解析zip 重…

es Elasticsearch 十一 Java api实现 索引管理

目录 Java api实现 索引管理 Pom 测试联通 增加索引 打印结果 异步执行 删除索引 查看索引是否存在 关闭索引 开启索引 Java api实现 索引管理 Pom <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-re…

C嘎嘎~~[谈谈C++的一些优化]

C的一些优化 匿名对象引用引用作形参引用作返回值 编译器优化构造 拷贝构造 ⇒ 构造拷贝构造 拷贝构造 ⇒ 一个拷贝构造 匿名对象 通过以前C语言的学习, 我们知道了有一种 具有临时性的, 没有名字的变量 — — 匿名变量. 那么我们的对象应该也有这个特性 — — 匿名对象 匿名…

如何在 Linux 中创建非登录用户?

在 Linux 系统中&#xff0c;用户账户的管理是一个重要的任务。除了常规的登录用户&#xff0c;有时候我们需要创建一些非登录用户&#xff0c;这些用户通常用于运行服务、执行特定任务或限制访问权限。 本文将详细介绍如何在 Linux 中创建非登录用户&#xff0c;并提供一些相关…

linuxOPS基础_linux系统注意事项

Linux严格区分大小写 Linux 和Windows不同&#xff0c;Linux严格区分大小写的&#xff0c;包括文件名和目录名、命令、命令选项、配置文件设置选项等。 例如&#xff0c;Win7 系统桌面上有文件夹叫做Test&#xff0c;当我们在桌面上再新建一个名为 test 的文件夹时&#xff0c…

Java之旅(四)

Java变量 变量是存储数据值的容器&#xff0c;用于在内存中保存数据。成员变量 作用范围是整个类 类的成员变量的作用范围同类的实例化对象的作用范围相同。当类被实例化的时候&#xff0c;成员变量就会在内存中分配空间&#xff0c;并初始化 实例变量&#xff08;不以 static…

如何在华为OD机试中获得满分?Java实现【基站维修工程师】一文详解!

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: Java华为OD机试真题(2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述4. Java算法源码5. 测试6.解题思路1. 题目描述 小陈是一名

Canvas实现连线动态效果

前言 这段时间一直在研究 Canvas 的动画&#xff0c;本文将带大家基于 Canvas 封装的 ZRender 库&#xff0c;了解ZRender 库中提供的 animate 绘制动画的方法&#xff0c;并且使用 animate 方法实现一个带有箭头流动效果的连线。 效果 ZRender 在介绍 ZRender 的动画之前&a…

java+iClientOpenlayers实现污水排放扩散模拟(湖库污染排放扩散模拟)

软件实现效果 一、应用背景 湖库污染是一个日益严峻的环境问题。随着城市化和工业化的加速发展&#xff0c;越来越多的有害物质被排放入湖库中&#xff0c;导致湖库污染加剧并扩散到周围地区。本文将探讨湖库污染扩散的原因、影响和解决方法。 首先&#xff0c;湖库污染扩散的…

Android之 软件架构发展和封装

一 简介 1.1 软件架构发展趋势是解耦&#xff0c;即分离数据层和视图层&#xff0c;使得数据层专注于业务的数据和逻辑处理。从而提高代码的可读可编辑效率&#xff0c;提高团队协作能力&#xff0c;项目的生产能力&#xff0c;降低后期维护成本。 1.2 Android架构发展MVC -…

Rocksdb相关学习

1 Basic Operations 先介绍一些 RocksDB 的基本操作和基本架构。 1.1 LSM 与 WriteBatch 参考文档5提到RocksDB 是一个快速存储系统&#xff0c;它会充分挖掘 Flash or RAM 硬件的读写特性&#xff0c;支持单个 KV 的读写以及批量读写。RocksDB 自身采用的一些数据结构如 LSM/…

STLINK V2 无法用STM32CubeProgrammer下载程序

这个问题真的挺狗的&#xff0c;先说结论&#xff0c;因为你买的STLINK V2是国产的&#xff0c;而且用的也是国产的芯片&#xff0c;不是ST的STM32F103C8T6&#xff0c;所以STM32CubeProgrammer识别不到芯片的串号&#xff0c;都是奸商为了省钱导致的。 我是去年买的一个STLINK…

数据库作业

数据库teaching中的表结构和表记录。    &#xff08;1&#xff09;学生信息表student    #student表结构      create table if not exists student (      studentno char(11) not null comment学号,      sname char(8) not null comment姓名,   …

【Unity100个实用小技巧】一行代码解决天空盒接缝问题

☀️博客主页&#xff1a;CSDN博客主页&#x1f4a8;本文由 萌萌的小木屋 原创&#xff0c;首发于 CSDN&#x1f4a2;&#x1f525;学习专栏推荐&#xff1a;面试汇总❗️游戏框架专栏推荐&#xff1a;游戏实用框架专栏⛅️点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd;&#…