【Linux】学习-基础IO拓展篇

Linux基础IO拓展篇—详解文件系统

理解文件系统

在Linux基础IO篇中,我们站在用户的视角对文件进行了理解,主要是针对被打开的文件,那么有没有没有被打开的文件呢?当然有!今天我们换个视角,来站在系统的角度侧重于磁盘级别的文件是如何被存储以及管理的

要了解磁盘文件,我们先来了解一下磁盘

磁盘文件

内存是一种掉电且易失存储的介质

磁盘是一种永久性存储介质,类似的还有SSD,U盘,flash卡,光盘,磁带,都是永久性存储介质

磁盘是一个外设,并且是我们计算机内部中唯一的一个机械设备,因此,其速度非常缓慢,所以操作系统一定会有一些提速方式来提高用户体验感。

磁盘基本知识

参考以下博文:

[磁盘的结构](5 分钟图解 磁盘的结构(盘片、磁道、扇区、柱面)_磁道和扇区_一剑何风情的博客-CSDN博客)

硬盘基本知识

了解完基本结构后,我们再来思考,数据存在磁盘的哪里呢?

  • 磁盘的盘面由一些磁性物质组成,可以用这些磁性物质来记录二进制数据

由于磁盘的磁道被分为一个个扇区,每个扇区就是一个“磁盘块‘,并且各个扇区的数据量是相同的(一般是512字节),因此越里面的扇区,其中二进制数据就越密集,越往外则相反。

如何在磁盘中读写数据?

  • 需要把”磁头“移动到想要读/写的扇区所在的磁道,磁盘会在音圈马达的带动下转起来,让目标扇区从磁头下划过,才能完成对扇区的读/写操作。

磁盘的物理寻址方式?—CHS寻址方式

  • 我们可以用柱面号,盘面号,扇区号来定义任意一个”磁盘块“。这个块号就可以转换成地址的形式

  • 根据此地址,我们就能读取一个”磁盘块“

  • 先根据”“柱面号”移动磁臂,让磁头指向指定柱面

  • 再根据“盘面号”激活指定盘面对应的磁头

  • 最后根据“扇区号”,在磁盘旋转时,指定的扇区会从磁头下面划过,这样就成功找到地址并完成读/写

文件元

文件由文件内容和文件属性构成,其中文件属性正是描述此文件的一些基本信息,比如文件名,大小以及创建时间,文件的属性由被称为元信息,也叫文件元数据:

当我们使用命令ls -l 显示的信息正是文件的属性—文件元信息:每行包含七列,其中有:

  • 模式
  • 硬链接数
  • 文件所有者
  • 大小
  • 最后修改时间
  • 文件名

image-20230925175431180

文件元还能通过命令stat来读取更详细的信息:

image-20230925210039170

文件内容与文件属性在磁盘中是分开存储的,其中保存文件元信息的结构为inode,称之为文件的编号,这个编号在所有的文件中是唯一且每个文件都有:

使用命令:ls -i 就可以查看每个文件对应的inode编号:

image-20230925205657236

在详细介绍inode之前,我们先来了解一下文件结构

文件系统

前面我们提到过,数据是存储在磁盘的盘面上的,而想要进行文件的读/写操作则通过CHS寻址法来找到对应的“磁盘块”。

那这种寻址法究竟是如何做到的呢,整个文件系统又是如何运作起来的呢?

我们不妨可以这样想象一下,磁盘是圆的,但我们可以将其向磁带一样抽象成线性结构,也就是将原本是圆形的磁盘拉成直带:

image-20230925210758095

image-20230926123047517

经过这样一个抽象的过程,我们可以将磁盘的管理,想象成对这个数组结构的管理,而CHS寻址方式,就是通过一系列操作,将数组下标转化成对应的柱面号,盘面号以及扇区号,这样一来,想要访问一个扇区,只需要知道数组下标即可

  • 将数据存储到磁盘,也就是将数据存储到数组
  • 找到磁盘特定的扇区位置,就变成了找到数组的特定位置
  • 对磁盘的管理也变成了对数组的管理

在我们的电脑中,有分为C盘和D盘,这又是什么意思呢?难道指的是哪个盘号吗?当然不是!磁盘会根据用户使用情况,进行磁盘分区,因此磁盘也叫块设备,分区的单位为扇区,也就是说,若磁盘上一共分了100个扇区,那么会根据用户的情况,将这100个盘区进行划分管理,比如C盘占有80个扇区,而D区占有20个扇区,这就是磁盘分区,

image-20230926123135512

这样一来,对磁盘的管理,又变成了对每个分区的管理,而每个分区都会初始化,也就是磁盘格式化,会对每个分区又进行细分管理,这就相当于磁盘是一个国家,而扇区相当于国家占有的面积的划分单位,国家又细分成省份,各个省份的占地面积都不同,也就是分到的扇区大小各异,而省份又会被分为各个市,也就是分区也是要被分出来管理的,但每个分区的管理框架都一样,只是填入的信息不同:

这是Linux ext2文件系统,上图为磁盘文件系统图(内核内存映像肯定有所不同),磁盘是典型的块设备,硬盘分区会被划分为一个个的block(框架)。一个block的大小是由格式化的时候确定的,并且不可以更改。例如mke2fs的-b选项可以设定block大小为1024、2048或4096字节。而上图中启动块(Boot Block)的大小是确定的,

  • Block Group:ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组成。

  • 超级块(Super Block):存放文件系统本身的结构信息。记录的信息主要有:bolck 和 inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了

  • GDT,Group Descriptor Table:块组描述符,描述块组属性信息

  • 块位图(Block Bitmap):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用

  • inode位图(inode Bitmap):每个bit表示一个inode是否空闲可用。

  • i节点表(inode Table):存放文件属性 如 文件大小,所有者,最近修改时间等

  • 数据区(Data blocks):存放文件内容

  • Super Block

Super Block是需要被备份的,因为磁盘有可能会出现物理上的数据丢失,其里面记录的整个文件分区的属性集合就会随之丢失,因此在每一个分区中都会有Super Block的备份,并且因为记录的都是整个分区的属性集合,因此看起来会很冗余,但也大大加强了对文件系统属性信息的保护。

  • Data block

数据块是多个4KB(扇区*8)大小的集合,保存的都是特定文件的内容

为什么不以扇区大小为单位?

  • 虽然磁盘的基本单位是扇区(512字节),但是操作系统(文件系统)和磁盘进行IO的基本单位是4KB,因此磁盘又被称为块设备,如果以512字节为单位进行IO会导致多次的IO,进而导致效率的降低。还有一个原因就是如果操作系统和磁盘使用一样的大小,如果换了磁盘使得磁盘大小变化,那么操作系统的源代码也得跟着变化,所以这样做有利于软硬件之间的解耦合。

  • inodeTable

前面我们提到过,Linux下文件内容与文件属性在磁盘中是分开存储的,其中保存文件元信息的结构为inode,称之为文件的编号,这个编号在所有的文件中是唯一且每个文件都有。

inode本质究竟是什么?

inode是一个大小为128字节的空间,保存的是对应文件的属性,inodeTable其实就是所有文件的inode空间的集合,由于每个文件都对应自己的属性,且inodeTable块组内存在着所有文件的inode空间与文件一一对应,因此这些空间是需要被标识且具有唯一性,也就是每一个inode空间都要对应一个inode编号,这样才能将文件对应的文件属性与inode联系起来并将文件属性保存在inode内。

一般而言,一个文件一个inode,一个inode编号,文件内容就在datablock中申请空间并写进去

  • Blockbitmap

blockbitmap利用位图的思想用来判断datablock有没有被占用,假设有100个datablock,就有100个比特位,每个比特位和特定的block是一一对应的,若比特位被置为1则表示该block被占用

  • inodebitmap

同理blockmap,inodebitmap也是利用了位图的思想,不过是用来判读inode空间有没有被占用

  • Group descriptor table

块组描述符,用来描述块组大小,已用空间,inode个数,被占用inode个数,剩余inode个数,datablock个数等到信息

一个文件只有对应一个inode编号,那只能有一个datablock吗?

肯定不是的!因为inode是描述文件属性的,文件的属性当然只能是特定的,因此只对应一个inode空间,在inode空间会存放该文件对应在数据块中申请的内容空间的位置,以此来找到对应的文件内容:

struct inode
{//文件大小//文件inode编号//其他属性//存放文件内容的数据块的位置int blocks[SIZE];   
};

创建一个文件,系统做了什么?又是如何将文件内容与属性分开存放的?

主要有四个操作:

  • 存储属性

    内核先遍历inodebitmap,找到一个空闲的i节点(这里是263466)并将此比特位置为1。然后在inodeTable中,找到此inode对应的inode空间,内核把文件信息记录到其中。

  • 存储数据

    该文件需要存储在三个磁盘块,内核找到了三个空闲块:300,500,800。将内核缓冲区的第一块数据

    复制到300,下一块复制到500,以此类推。

  • 记录分配情况

    文件内容按顺序300,500,800存放。内核在inode上的磁盘分布区记录了上述块列表。也就是将块编号填入了inode中

  • 添加文件名到目录

    新的文件名abc。linux如何在当前的目录中记录这个文件?内核将入口(263466,abc)添加到目录文

    件。文件名和inode之间的对应关系将文件名和文件的内容及属性连接起来。

理解创建文件名的最后一步:添加文件名到目录

  • 目录本身也是文件,有自己的datablock,其datablock中存储的是目录存放的文件的文件名与inode间的映射关系,因此创建文件最后一步,就是要把文件名与inode的映射关系通过写到磁盘上目录对应的datablock中,因此同一目录下文件名不能重复也就是因为inode是唯一的。这也能解释为什么创建文件要有写权限,访问文件名需要有r权限,因为创建文件就是对目录文件的datablock进行写入的过程!访问文件名则需要到目录文件的datablock读的过程!

为什么删除文件比创建文件快?

  • 因为删除文件只需要将inodebitmap中对应的inode编号和blockbitmap对应的数据块位置 置为0->无效化。而inodeTable中对应的inode空间和datablock中的内容是不做处理的,因为不需要,他们是可以被覆盖写的,所以删除文件速度快,顺便说一下,如果误操作删除了文件,短时间内是可以恢复的,只要不进行创建文件等操作将被删除的inode号申请走了并进行了覆盖,在下一次被覆盖之前,都可以恢复。

以上就是文件系统的全部内容,如果有帮助的话,你的三连是我学习的最大动力!如果有不正确的内容,欢迎批评指正!!

软硬链接

是不做处理的,因为不需要,他们是可以被覆盖写的,所以删除文件速度快,顺便说一下,如果误操作删除了文件,短时间内是可以恢复的,只要不进行创建文件等操作将被删除的inode号申请走了并进行了覆盖,在下一次被覆盖之前,都可以恢复。

以上就是文件系统的全部内容,如果有帮助的话,你的三连是我学习的最大动力!如果有不正确的内容,欢迎批评指正!!

软硬链接

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【python5】闭包/装饰器,

文章目录 1.闭包和装饰器:函数里return就是闭包2.解析eeprom:如下是二进制文件,C8是一个字节3.json/configparser/optparse:json.dumps(将字典转化为字符串,将json信息写进文件),jso…

2024.02.11作业

1.请使用递归实现n! #include <stdio.h> #include <stdlib.h> #include <string.h>int func(int n) {if (n 1){return 1;}return func(n - 1) * n; }int main() {int n 5;printf("%d\n", func(5));return 0; } 2.请使用递归实现0-n的和 #inclu…

Kafka集群安装与部署

集群规划 准备工作 安装 安装包下载&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1BtSiaf1ptLKdJiA36CyxJg?pwd6666 Kafka安装与配置 1、上传并解压安装包 tar -zxvf kafka_2.12-3.3.1.tgz -C /opt/moudle/2、修改解压后的文件名称 mv kafka_2.12-3.3.1/ kafka…

《动手学深度学习(PyTorch版)》笔记8.5

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过&…

政安晨:在Jupyter中【示例演绎】Matplotlib的官方指南(一){Pyplot tutorial}

介绍 Matplotlib是一个Python的绘图库&#xff0c;可以用于创建各种静态、动态、交互式的图表和可视化效果。它提供了一种方便的方式来可视化数据&#xff0c;并支持多种图表类型&#xff0c;包括线图、散点图、柱状图、饼图、等高线图等。 Matplotlib可以与NumPy一起使用&am…

JavaScript 跨窗口通信(Cross-Window Communication)

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ ​ ✨ 前言 在现代 Web 开发中&#xff0c;跨窗口通信是一种常见需求。它允许在…

力扣49. 字母异位词分组

Problem: 49. 字母异位词分组 文章目录 题目描述思路复杂度Code 题目描述 思路 1.我们利用一个无序映射以排序后的字符作为键、字符数组作为值&#xff1b; 2.每次我们从原始数组中取出一个字符串并对其进行排序&#xff0c;并将其添加到对应键所存的数组中&#xff1b; 3.创建…

【51单片机】串口通信实验(包括波特率如何计算)

目录 串口通信实验通信的基本概念串行通信与并行通信异步通信与同步通信单工、 半双工与全双工通信通信速率 51单片机串口介绍串口介绍串口通信简介串口相关寄存器串口工作方式方式0方式1方式 2 和方式 3 串口的使用方法&#xff08;计算波特率&#xff09; 硬件设计软件设计1、…

JavaScript中的for循环和map方法

JavaScript中的for循环和map方法 在JavaScript中&#xff0c;循环是一种常见的编程技巧&#xff0c;用于重复执行一段代码。for循环和map方法都可以用于循环操作&#xff0c;但它们在语法和应用场景上存在一些区别。本文将详细讲解JavaScript中的for循环和map方法&#xff0c;以…

Python 线性回归可视化 并将回归函数放置到图像上

import matplotlib.pyplot as plt import scipy import seaborn as sns# 加载内置的数据集 df sns.load_dataset(tips)#create regplot p sns.regplot(xtotal_bill, ytip, datadf)#calculate slope and intercept of regression equation slope, intercept, r, p, sterr sci…

蓝桥杯每日一题------背包问题(二)

前言 本次讲解背包问题的一些延申问题&#xff0c;新的知识点主要涉及到二进制优化&#xff0c;单调队列优化DP&#xff0c;树形DP等。 多重背包 原始做法 多重背包的题意处在01背包和完全背包之间&#xff0c;因为对于每一个物品它规定了可选的个数&#xff0c;那么可以考虑…

python+django高校教务选课成绩系统v0143

系统主要实现了以下功能模块&#xff1a; 本课题使用Python语言进行开发。基于web,代码层面的操作主要在PyCharm中进行&#xff0c;将系统所使用到的表以及数据存储到MySQL数据库中 使用说明 使用Navicat或者其它工具&#xff0c;在mysql中创建对应名称的数据库&#xff0c;并…