认识硬件 – 磁盘
磁盘是计算机上唯一的一个机械设备, 也是一个外设。
文件系统
分区
假设我们的磁盘有800个G, 800个G太大了, 所以我们对这800个G进行分区管理, 于是现在就变成了每个分区只需要管理好自己的200个G左右的空间就好了, 但是即使是只有200个G的空间, 也没有那么的好管理
BootBlock
位于分区的头部, 这个区域通常是记录操作系统启动的相关信息, 这个区域我们不重点学习。
除了上面那个区域, 其他的区域被换分为n个block group
所以我们对磁盘的管理, 就变成了我们对一个分区的管理, 只要我们了解了操作系统是如何管理这个分区的, 我们就可以知道操作系统是怎么管理磁盘的了, 这种思想我们称为分治
;
Date blocks
Date blocks
存文件内容的区域, 以块的形式呈现, 常见是以4KB
为一块, (也就是说, 哪怕我们现在只需要往磁盘里写1字节内容, 那么在文件系统当中, 都要在某一个分区里面, 找到某一个块组, 然后再这个块组里面申请一个块, 这个块的大小就得是4KB对应磁盘就是分配8个扇区给你(每个扇区512字节))
inode table
inode table
inode:保存的是单个文件的所有属性, 比如该文件的创建时间, 权限, 以及在Date block中占用了哪些块
,128字节, 一般而言, 一个文件一个inode
而inode table 里会有多个inode, 每个inode都有自己的编号
inode的设置是以分区为单位的, 不能跨分区使用, 比如你在1组里有个inode编号为1 的文件, 在2组里是可以也存在一个inode编号为1的文件的
inode内有文件的所有属性, 但是文件名不属于inode内的属性
在Linux中标识某个文件其实用的是inode
编号。
问题
讲到这里大家可能会有点懵逼, 但是我平常使用的都是文件名啊, 你说Linux标识文件用的是编号, 那我的文件名是怎么转化成编号的呢? 不急, 我们稍后再谈。
如果我们想查看某个文件的编号可以使用ls的 -i
选项
这个919516就是文件的编号
inode
接下来我们将inode table 和 Date block 联动起来讲
我们来细讲一下inode里怎么存储文件所使用的块的
首先是一级索引
比如图中的1 - 11
这些索引所指向的块, 就是存储我们文件内容的块
然后是二级索引
图中12, 13
, 这些索引指向的块是存储的是一级索引
, 然后再由一级索引去指向文件内容
最后是三级索引
, 图中14
, 他指向的块存储的是二级索引
, 然后这些二级索引指向一级索引, 最后再有这些一级索引指向文件内容
block bitmap
下一个我们来谈block bitmap
, 其实他的作用, 就是存储我们Date block中哪些哪些块被使用了, 哪些块没被使用, 他的方法就是利用位图, 将比特位和块号建立映射, 表示该块号是否被使用
到这里其实我们可以回答一个问题
删除一个文件的时候, 需不需要将该文件所使用的块(文件内容)清空?
不需要, 我们只需要找到该文件的inode然后找到该文件的使用的块, 然后在block table里将他所使用的块标记为未使用即可
inode bitmap
inode bitmap
的功能是将比特位和inode编号建立映射, 比特位的内容表示inode table
中该编号的inode是否有效。
同理, 删除文件的时候, 只需要将inode bitmap中表示该文件的比特位清空即可
所以我们在删除文件的时候, 只需要操作inode botmap 和 block bitmap即可;
如何恢复被删除的文件(理论)
所以我们在删除文件的时候, 这个文件其实是没有被删除的, 如果我们此时想把一个文件恢复回来, 我们此时需要做什么操作?, 我们只要找到这个被删文件的inode编号, 然后在inode bitmap里,再将该编号的比特位改为1, 然后再在inode table 找到该inode 就能读到他的属性了, 读到属性后再去读取他的block
, 最后在通过block去block bitmap里, 将他所用到的块号所对应的比特位置1;
至于怎么找到被删文件的inode编号呢, Linux中有一个日志, 是会保存用户最近删除的文件信息的这个信息里就有该文件对应的文件编号的。
group descriptor table
gdp
描述了这个分组的所有属性, 这个分分组有多少个块, 被使用的有多少, 没被使用的有多少, 分配inode编号的时候, 下一个应该从哪里开始分配, 等等等, 与这个组相关的所有属性全部都放在这里面, 他描述了整个分组的基本的使用情况
super block
super block 描述的是整个分区的文件系统的基本情况 , 注意数分区
,我们这个分组可能只占了10个G 但是这个组所在的分区可能占200个G, 而super block 描述的是这个分区的文件系统的基本情况
比如:
这整个分区, 从哪到哪属于第组; 整个分区对应使用inode 的情况, 整个分区, 对应的组里面的使用率是多少, 这个文件系统, 允不允许用户使用, 允许哪些用户去使用
super block 不会在每个分组里都有, 有些group是有的, 有些是没有的 , 为什么要这样呢?
1 如果每个组都有那么有点浪费, 而且在更新的时候效率过低。
2 如果只存在一份, 那么一旦这段区域出故障了, 整个分区将无法正常运行。
这也就是为什么, 有时候我们的电脑挂掉了, 然后显示正在检查文件完整性, 请勿关机
, 其实就可能是你的某个区的super block挂掉了, 然后系统在别的分组里找正常的super block拷贝过来修复。
如果这些属性初始没有被设置, 那么我们无法正常使用。
这个初始化操作其实就是我们常说的格式化
新建一个文件系统要做些什么?
首先根据你所在的目录
, 确定你在哪个分区, 然后为该文件分配inode编号, 然后在inode bitmap里将该位置置1, 然后填写文件的属性, 分析文件内容需要多少个块, 然后去block bitmap里申请没用过的块, 用inode中的block数组指向这些使用的块, 最后将数据写进去就好了。
删除一个文件系统要做些什么?
首先根据你所在的目录
, 确定你在哪个分区, 然后根据你的inode范围确定你在哪个分组的, 然后通过你inode里的属性在block bitmap里将你使用的块的编号置0, 最后在inode bitmap里将该文件对应的编号置0即可, 因为我们其实不需要对Date block
做任何修改, 所以我们的删除操作其实是特别快的。
查找一个文件系统要做些什么?
首先是去inode table 里确定你这个文件是否有效, 如果有效我们就去读取对应的inode table, 然后根据inode将他对应的属性拼接起来交给你。
我们怎么知道一个文件的inode?(我只知道文件的名字)
使用者从来都是用的文件名
, 没关心过inode
,
如何理解"目录"
目录也是文件, 有自己的inode。
目录也有自己的属性。
目录有内容吗?(目录要不要数据块)
目录也有数据块!
数据块里面放什么呢?
里面放的是, 该目录下文件的文件名, 和对应文件的inode的映射该系。
到这里我们就理解了:
1 同一个目录下不能有同名文件了, 文件名是作为key值找到对应的inode的
2 目录下, 没有读权限我们无法创建文件如果我们没有写权限, 就没法将创建的文件名和对应的inode写进目录里
3 目录下, 没有读权限我们是无法查看文件以为我们要读取这个文件, 的去读取他所在目录, 找到该文件的inode值
4 目录下, 没有执行权限我们无法进入该目录, cd的时候 我们判断一下, 如果你当前目录的inode里灭有x权限, 就不让你成功cd
我怎么知道目录的inode呢?
目录的inode是在他的上级
目录里面存着的, 他的上级目录的inode是存在他的上上级
目录里的, 这样一直查找, 直到根目录
, 根目录的文件名是确定的, 他的inode也是确定的。所以我们在找某个目录的时候, 要一路递归到根目录, 然后再一路返回, 最后才能找到我们的inode。
访问任何一个文件, 都必须带上对应的路径
,这样我们才能一路找到他的inode
由于每次访问一个文件都需要从根目录开始寻找, 这样效率太慢, 所以Linux会有一个机制叫做dentry
缓存, 他会将我们常访问的文件的inode缓存起来, 我们在使用的时候, 直接去里面拿就好了, 不需要直接递归的去找。
软链接
###创建软链接
使用ln -s 文件名, 文件名
创建一个后者指向前者的软链接
可以看到这个两个文件的inode不一样, 说明这两个文件不是一个文件, 因为一个inode对应一个文件
软链接是一个独立的文件, 有独立的数据块, 他的数据块里放的是, 他所指向的文件的路径
所以我们是可以直接通过软链接访问到他指向的文件的。
如果我们将软链接删掉了那么对原文件没有影响, 但是如果我们把原文件给删掉了, 那么这个软链接就没用了。
这个软链接就类似我们Window中的快捷方式
删除的块可以使用rm
删除 也可以使用unlink
删除
硬链接
使用ls 文件名 文件名
创建一个后者指向前者的硬链接
可以看到test.txt 和 hard-link 前面的数字是2 而 log.txt 和 solft-link前面的数字是1。
这个数字其实表示的是硬链接数
我们可以看到这两的inode是一样的, 所以我们得出结论
硬链接不是一个独立的文件因为他没有独立的inode
。
如何理解硬链接
所谓的建立硬链接其实本质上, 就是在特定目录的数据块中, 新增文件名和指向文件名的inode编号。
, 所以他没有建立新的文件, 而是起了个名字然后指向别的文件的inode。
如果我们删掉硬链接指向的文件, 那么硬链接前面的数字(硬链接数)就会变成1, 但是文件的inode没变, 也就是被我们删掉的文件其实还在, 只是被换了个名字, 类似于取别名。
结论
任意一个文件, 无论是目录还是普通文件都有inode, 每个inode内部都有一个叫做引用计数的计数器
表示有多少个文件名, 指向该文件。
所以当我们在删除一个文件的时候, 系统会将这个引用计数器减1, 知道被减为0了这个文件才真正的被删除
这也是为什么刚刚我们在删除硬链接指向的文件后, 硬链接指向的文件还在的原因
软链接应用场景
就像Windows里的快捷方式一样, 方便用户去使用软链接所指向的文件, 有时候, 我们需要运行的程序在一大堆目录里藏得太深了, 为了方便我们去使用他, 我们就可以创建一个软链接, 然后将这个软链接放在方便找的地方。
硬链接应用场景
我们在创建一个普通文件的时候, 默认这个文件的硬链接数是1.
但是如果我们创建一个目录的时候, 却看到这个目录文件的默认硬链接数是2
这是因为, 当我们在创建目录的时候, 默认目录里会包含两个隐藏文件.
和..
可以看到这个.
的inode和我们当前目录的inode是一致的, 所以他其实就是一个硬连接。同理 这个..
也就是上级目录的硬链接;
Linux就是靠的硬连接来维持整个目录结构的。
结论 : 硬连接通常用于路径定位
采用硬连接可以进行, 路径的切换。
Linux不允许用户对目录进行硬连接
, 因为由用户进行的硬连接可能会导致Linux的多叉树结构中产生环, 从而导致一些执行(如 find)出现bug