按照我个人的理解慢慢说,可能顺序不是很流畅,但是我尽量说的通畅一点。
先梳理自己的思路,再慢慢整理格式。 先想下怎么写文章的脉络
写一篇文章真的好慢啊!!!
先写大概 脉络结构,后面再整理文字。 最后自己再组织语言。
本意: 是梳理自己的理解,让自己更好讲解,但是写着写着方法,还是别人的思路 这真的不好, 这只能说明理解的还是不深,加强理解。 可以去除一些多余的解释
写作思路,带着问题 解决问题
1. 文件系统的来源
在电脑中容量比较大的存储介质是:磁盘。 (关于磁盘的介绍不在此多引申)
所谓的文件系统,就是按照我们比较容易理解的文件概念(似乎看的到),把其对应的结构和数据保存在磁盘中。
如同我们装机时候一样,把文件系统的内容保存到磁盘上,需要以下几个小步骤。
- 初始化,分区
- 用文件系统格式化
- 挂载
单独说的步骤1,2,3 总是觉得莫名其妙,但是看下每一步做的工作,以后最后形成的系统格式。 那么每一步的必然性就很明显了。
第一步: 可以通过在虚拟机上添加一块移动硬盘,然后进行模拟分区
分区之后
第二步: 文件系统有很多种不同的文件格式
可以使用命令 mkfs 来预览
选择比较常用的 ext4 进行格式化分区
注意:看上图 ext 文件系统格式化 分区 sdb1 之后的提示信息,特别重要
重要的备注信息如下 :
- 261888 4k 大小的 blocks
- 65536 inodes
- superblock
- inode table
因为正是这些,属于文件系统的基本结构,决定了文件怎么读写 来使用的,后续介绍文件的时候,这里面的概念会一直论述。
第三步: : 挂载到不同的目录
之后对挂载文件夹内mnt的操作,就是等同于磁盘的操作了。
如果当前inode 有挂载信息,那么它本身的文件功能会被忽略。 查找文件的时候也是这样,后面具体解释
错误 tips
- 如果不格式化 直接挂载
如果按照结构体的顺序来介绍,会感觉一下子把人给搞楞,搞的迷糊。 为了简单说明,我们为什么这么做之前,我们先来看看我们用文件系统作甚本,然后循环渐进的引入不同的术语和概念
术语真是不同程序员之间交流的关键,可以减少很多交流偏差成本。
2. 文件是什么?
查看 :我们在电脑上或者客户端看到的文件和文件夹(前面已经说过,他们是以一定的形式保存在磁盘上)
开发使用:用户通过系统调用,来进行 read
, write
我们知道,磁盘是通过扇区保存00011
这些字节来保存数据的,以及磁盘的最小单位是扇区。
本质上,我们读取或者写入,都是选择固定磁道的 Noxxx 扇区,来进行数据的读写
2.1 文件的信息内容
磁盘是如何保存是文件的?文件的格式是什么? 他是如何读存的? 带着这些问题,我们来看看文件的具体内容。
先按照我们日常使用习惯,进入一个目录,查看一个文件的详细信息
ls -ahl -i
第一列 :比如 262547,就是文件的 inode。
我们日常都是通过 inode 查找文件信息 和 文件内容。
2.2 新建一个文件
当文件系统新建一个文件,比如 新建一个hello.txt 时,是如何记录文件的。
上图分为二部分,第一部分是 inodetable ,第二部分是 data。
我们通过inode table 选择一个空闲地址,生成一个 inode 节点,然后再data层保存数据,之后把数据的地址回写入到 inode 的结构体上。
比如 table 中会保存,文件inode 节点对应的 扇区地址编号
(上面的图 为了更好说明,为了更好理解 不做纠错)
通过上图我们来查询一个文件的时候,可以定位到固定的扇区,然后通过磁盘寻道读取内容
2.3 block
不同的文件系统 ,扇区的大小不一样,有的 512b,有的1024b 等等。 为了统一化,引入了一个中间层 block
比如定义 block 大小为4k,不同的文件系统,不同大小的扇区,可以用不同的数量来填充。
比如 用4个 1024B的扇区,8个512B的扇区来来实现。 这样保证了每个block的大小是相同的。
所谓磁盘的最小单位是: 扇区
文件的最小单位是: 块
这也就是开头所说的,分区之后包含的 多少个 block。
2.4 存储映射
如图所示,当我们查看文件内容时,我们按照一定的规则找到该文件的inode,然后通过inode 获取文件的数据。
大的文件,可能保存在n个block中。(比如一部4G的mv,可能需要很多个block)
小的文件,用一个block来保存。
通过block 关联的扇区,就是记录文件的内容。
(如果更好的利用局部性,以及按照一定的电梯算法)通过记录的扇区,按照先后顺序,开始旋转磁道,读取数据到内存。
2.5 inode 记录了什么信息
linux 根据 inode 查找文件的存储位置和文件信息
2.6 inode table
找到一个空闲的inode ,然后存储到 block,然后把地址写到 inode 上
每一个文件,都需要一个inode 节点来描述
3. super block
我们通过 stat 可以查看文件的使用情况。
但是我们在新建一个文件的时候,需要分配 inode 和 data addr 对应的block
他们是如何知道自己系统中,还有空闲的inode 和 block。
所以次数就需要一个字段,或者说结构体来记录 当前文件的 inode和 block的使用情况。
让我们先把话题回溯到磁盘的格式化,看看他们做了什么工作。
磁盘的结构 :
MBR : 记录了开启启动的一些信息
磁盘分区的结构 :
- boot sector
- ext 文件系统
不同的分区可以使用不同的文件系统
文件系统中,通过 super block 来记录 整个文件系统的使用信息。
每一个 block group中,使用 block bitmap 和 inode bitmap 记录group内 inode 和 data的使用情况。
便于分配和管理。
先从 data block 找一个空闲的存放文件的数据,然后从 innode table 找一个空闲的节点 描述文件的地址和属性
,存放 data block 的地址
所以新建文件的时候,这二个位置会发生变化。
super block : 在磁盘分区的时候,特别说过。
至此,我们在整体的看下 文件在磁盘上的存储
我们是如何查找到一个文件的 ,在找到文件path 之前我们先了解下 目录
4. 目录和目录项
4.1 问题的引入
inode 信息保存的是 文件的各种信息,具体的我们可以看下他的 struct,里面的字段。
我们都是通过inode 来查找文件。
但是inode没有保存文件名,用户习惯是通过文件名来查找文件内容。
4.2 目录
datablock 文件保存的是数据,目录存放的是 表格
如果查看一个文件, 根据path
首先先找 根目录 的 inode 这个目录,文件内容是表格。
找到 /bin 的地址是 6029313. 的inode 编号
inode table 查找到对应的inode 节点 包括文件的名称。
inode 有一个约束 2:一定是根目录的 inode
1 : 一般代表文件初始化保留的
5. 文件path
文件的相对路径 :
文件夹的 . 和 ..
分别对应 当前目录的硬链接 和 上级目录的硬链接。
然后通过上级目录的 block table 一点一点回溯找到
6. 挂载
父文件系统是 电脑磁盘上的系统
子文件系统: 可以是 U盘 移动硬盘上的文件
6.2 如何访问一个U盘的文件
从根目录寻址path,到固定的inode ,如果编辑为没有挂载,那么就访问文件。
如果标记为已经挂载,那么久去 hash table 里面找挂载的 vfsmout 信息,找到挂载点 的根目录
然后依次找到path 下的文件
这也解释了为什么,一个文件夹目录被挂载之后,之前的文件无法访问和读写了
7. VFS
8. 文件描述符
文件是如何动态操作一个文件的
可以参考操作系统的?, 结构体的概念
fd 是内核空间返回给用户空间的 句柄
8.2 一个进程打开的文件
fd 更多是数组的偏移
9. 硬链接和软连接
进程在
通过前面的了解,已经知道了文件在磁盘上的存储
- 硬链接
相同的inode 和 data block
- 软链接--符号链接 ---快捷方式
软链接 本身是一个文件,文件内容 保存的是一个文件地址 path
硬链接 相当于一个 别名
软链接的内容 : 就是一个路径名
9.2 二者的区别
硬链接不能跨越分区
不同分区,有不同的inode
软连接可以跨越,是因为他存放的是 文件内容,文件内容就是一个路径名
硬链接不能ln 目录
目录下 . 本身就是一个硬链接
再建立 硬链接的时候 执行文件比较混乱。 所以禁止 对目录建立硬链接
10. 查看文件的使用情况 stat
du 是深入群众,查看每一个目录的文件的大小
du 是用来统计每个目录的大小
100. 致敬
王利涛老师的讲解真的是太好了
如果有看到这篇文章,感觉我说的很不清楚的,可以去观摩王老师的精彩讲解
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。