【Linux】基础IO(二)--- 理解内核级和用户级缓冲区、磁盘与ext系列文件系统、inode与软硬连接(下)

简介: 【Linux】基础IO(二)--- 理解内核级和用户级缓冲区、磁盘与ext系列文件系统、inode与软硬连接(下)

2 磁盘的具体物理存储结构


存储的基本单元:扇区 ---- 一般磁盘,所有的扇区都是512字节

同半径的所有扇区 — 称为 : 磁道

如何定位一个扇区?


磁盘中定位一个扇区需要知道它所在的柱面号、磁头号和扇区号,这三个参数构成了磁盘的物理地址。

磁盘中定位一个扇区的过程分为两步:第一步是寻道,即将磁头移动到目标柱面上;第二步是旋转延迟,即等待目标扇区旋转到磁头下方。

磁盘中定位一个扇区的时间取决于寻道时间和旋转延迟时间,寻道时间与磁头移动的距离有关,旋转延迟时间与磁盘的转速有关。

磁盘中定位一个扇区的方法有多种,常见的有CHS(柱面-磁头-扇区)方法、LBA(逻辑块地址)方法和GPT(全局唯一标识分区表)方法。


d31903723e544b4dbf4e464a28feb5fa.png

483284a5841f4ea79b05e5e45ee8e011.png



3 进行逻辑抽象


谈到过物理层面定位某个扇区运用的算法是CHS定位法,那么LBA如何转到CHS定位呢?其实很简单,只需通过一些计算方式就可以进行转换,下面图片中的计算方法是捏出来的数据,方便大家理解LBA转到CHS定位的过程。

H磁头用来判断是哪个扇面,C柱面用来判断是哪个磁道,S就是确定在具体扇面的具体磁道中的具体某个扇区,这些工作在软件层面都可以解决,解决的过程其实就是LBA转到CHS的过程。


bcb48f02db8a4c5380a8422bb42d04da.png


为什么OS要进行磁盘的逻辑抽象呢?直接用CHS定位不行吗?

其实有两个原因,第一点是便于管理:在软件层面OS只要管理一个线性数组就可以了,而在物理层面管理一个三维立体结构可不是轻松的。最重要的第二点是:不想让OS的代码和硬件强耦合,因为如果强耦合,底层换了存储设备由SSD换成HHD,OS的代码就失效了,而如果进行逻辑抽象的话,底层无论更换任何存储设备,在操作系统看来都不过只是一个线性数组结构罢了,适应性很强。


4 磁盘文件的管理

磁盘文件的管理思想 — 分而治之

操作系统对磁盘空间的抽象 — 数据块 一般是4kb大小


至于为什么选择4KB为基本单位,之前的计算机科学家做过测试,发现以4KB作为IO的基本单位,性能是最好的,所以文件系统就采用了4KB了,这背后都是有论文作为依据的。

早些年诞生一项理论,叫做局部性原理,这项理论证明,当计算机访问某些数据时,极大可能访问到它周围的数据,所以在进程IO数据时,多加载一些数据是有助于提高操作系统的效率的,并且在一定程度上减缓了数据多次IO的过程。顺序表相比链表优势便在于数据更加集中,缓存时数据的命中率更高。

所以多加载数据的原因就是,达到预加载数据和以空间换时间的目的!!!


所以真实的内存被划分是以4KB作为基本数据大小的空间,16G内存的笔记本中大约有4194304个基本数据大小的空间,这些空间叫做页框,就是内存中一个个的块。

磁盘中的文件,尤其是可执行文件,实际上也是按照4KB大小划分为一个个的块,可执行文件中的一个个块叫做页帧。

所以从磁盘中加载数据到内存时,就是分为一个个的块进行加载,将页帧的数据加载到页框里,这就是文件系统和内存管理之间的耦合,他们都是以4KB为大小进行划分的。


磁盘分区的各个区的管理策略都是相同的,只要把管理方法ctrl+c,ctrl+v就可以解决其他区的管理问题了,区域中细分的组之间的管理策略也是如此,所以在管理时,我们只要管理好细分的组便可以管理好磁盘这一大块空间了。


从磁盘文件管理角度为什么有类型?操作系统的访问方式就是起始地址加上偏移地址这么访问的。所以只需要知道数据块的起始地址即可访问对应数据内容

所以块的地址本质就是:数组的一个下标,N,我们采用线性下标N的方式,就能定位任何一个块了

介绍下位图:


文件系统中的位图是一种数据结构,用来表示有限域中的稠集,即每个元素至少出现一次,没有其他的数据和元素相关联。文件系统中的位图通常用来标记磁盘空间的分配情况,每个比特位对应一个磁盘块,0表示空闲,1表示占用。


5 理解ext系列文件系统(以ext2为例)


我们可以通过ls -l读取存储在磁盘上的文件信息,然后显示出来


cfb12cee458f441582def5c1a162c5cd.png


其实这个信息除了通过这种方式来读取,还有一个stat命令能够看到更多信息:

[root@localhost linux]# stat test.c
 File: "test.c"
 Size: 654 Blocks: 8 IO Block: 4096 普通文件
Device: 802h/2050d Inode: 263715 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2017-09-13 14:56:57.059012947 +0800
Modify: 2017-09-13 14:56:40.067012944 +0800
Change: 2017-09-13 14:56:40.069012948 +0800


inode


inode表是文件系统中的一种数据结构,它存放了文件的元数据信息,如inode号、大小、属性、时间等。 inode表中的每个条目叫做inode,它是文件或目录在一个文件系统中的唯一标识。


inode表的内容可以用·stat命令或ls -i命令来查看。 例如,如果你有一个文件叫file.txt,你可以用stat file.txt来查看它的inode信息,如下:

$ stat file.txt
  File: file.txt
  Size: 13              Blocks: 8          IO Block: 4096   regular file
Device: fd02h/64770d    Inode: 123456      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2022-10-05 10:00:00.000000000 +0800
Modify: 2022-10-05 10:00:00.000000000 +0800
Change: 2022-10-05 10:00:00.000000000 +0800
 Birth: -


从上面的输出可以看出,file.txt的inode号是123456,它的大小是13字节,它的权限是0644,它的所有者是root,它的修改时间是2022-10-05 10:00:00等等。


你也可以用ls -i file.txt来查看它的inode号,如下:

$ ls -i file.txt
123456 file.txt


从上面的输出可以看出,file.txt的inode号是123456。

为了能解释清楚inode我们先简单了解一下文件系统



baa53c162e5c4d178a60fcd8ebb0e3c7.png



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:块组描述符,描述块组属性信息,有兴趣的同学可以在了解一下 块位图(BlockBitmap):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没 有被占用


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


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


数据区:存放文件内容


可以说super block时文件系统的控制块 — 代表整个分区(或者说整个文件系统)的情况 保存文件系统的所有属性信息 (很重要!)---- 多份super block 就是为了防止故障发生,整个分区都不可以使用,起备份的作用!同时每个分区又分为不同的块组(block group),每个块组中都存在超级块,块组描述符— 记录块组宏各个部分的位置和大小,如位图、inode表等;数据块位图 — 记录块组中哪些数据块已经被使用,哪些没被使用;inode位图 – 记录了哪些inode已经被使用,哪些没有; inode表 — 存放了文件的元数据信息,如inode号、大小、属性、时间等;以及数据块 —存放了文件的实际内容或者指向其他数据块的指针(当然数据块data blocks 占据块组的百分之九十九的内存)


inode bit map 和block bit map的关系是什么 ?并行关系 一个管理inode的属性 一个管理数据


查看inode ---- ls -il


怎么理解inode?


ac8f852fd3e44ec98df6675ac4f07e9f.png


touch一个新文件看看


将属性和数据分开存放的想法看起来很简单,但实际上是如何工作的呢?我们通过touch一个新文件来看看如何工作


[root@localhost linux]# touch abc
[root@localhost linux]# ls -i abc
263466 abc


d53f9f7a32ba4ae9af44ae6f569e5d96.png


创建一个新文件主要有一下4个操作:


存储属性

内核先找到一个空闲的i节点(这里是263466)。内核把文件信息记录到其中。

存储数据

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

记录分配情况

文件内容按顺序300,500,800存放。内核在inode上的磁盘分布区记录了上述块列表。

添加文件名到目录

新的文件名abc。linux如何在当前的目录中记录这个文件?内核将入口(263466,abc)添加到目录文件。文件名和inode之间的对应关系将文件名和文件的内容及属性连接起来。


inode表中的datablock数组


inode表中的datablock数组是一个指针数组,它用来存储文件的数据块的地址。datablock数组的长度和文件系统的类型有关,一般有12个或15个指针。


datablock数组中的指针分为以下几种类型:


直接指针:直接指向文件的数据块,一般有12个,可以存储48KB(假设块大小为4KB)的文件数据。

间接指针:指向一个间接块,间接块中存放了多个直接指针,一般有一个,可以存储4MB(假设块大小为4KB,每个指针占4字节)的文件数据。

双重间接指针:指向一个双重间接块,双重间接块中存放了多个间接指针,一般有一个,可以存储4GB(假设块大小为4KB,每个指针占4字节)的文件数据。

三重间接指针:指向一个三重间接块,三重间接块中存放了多个双重间接指针,一般有一个,可以存储4TB(假设块大小为4KB,每个指针占4字节)的文件数据。


这样的结构可以让inode表中的inode占用较少的空间,同时可以支持较大的文件。


63d6d2a184044001932e27aa66f7b61f.png



再次理解


如何理解文件名 ---- 在目录文件内,文件名和inode互为key值 即映射关系


bed78cca3c5d4be7bf8f8764dbeef368.png

如何理解文件访问 — 一个目录也是一个文件,也有inode


d91f8b23c51341f990b0195e7a8822d3.png


如何理解文件的增删查改

  1. 查就是通过目录文件的数据信息进行查找
  2. 怎么删除文件 — 为什么删除这么快 — 很简单,因为只是修改了inode位图


5586a0cb5c414f52b9f0f93b9d6a9d94.png


  1. inode 不会被删 只会被覆盖 ---- bit map 置0 即删除 等待下次覆盖

格式化是什么? 其实就是对属性信息做操作,如bit map清空,描述符初始化

6 理解软硬理解


软硬链接是Linux系统中的两种文件链接方式,它们可以为一个文件创建多个有效的路径名。


软链接(也叫符号链接)类似于Windows系统中的快捷方式,它是一个特殊的文件,其中包含了另一个文件的路径名。软链接可以跨文件系统,可以对目录或不存在的文件名进行链接,但是如果原文件被删除了,软链接就会失效。


硬链接是指为一个文件创建一个或多个文件名,它们都指向同一个索引节点(inode),也就是同一个数据块。 硬链接不能跨文件系统,不能对目录进行链接,也不能对不存在的文件名进行链接,但是如果原文件被删除了,硬链接仍然有效。


在Linux系统中,可以用ln命令来创建软硬链接。


创建软链接:ln -s 源文件 目标文件

创建硬链接:ln 源文件 目标文件

软链接是一个独立的链接文件,有自己的inode number ,所以必有自己的inode属性和内容


软连接应用场景 — 本质其实就相当于快捷方式


4134b3a483744e4299bc73a890396851.png

那软连接的属性我们知道了,它的内容放的是什么呢?就是指向源文件的地址字符串


45fd88f616524c7f912f9da756909600.png

其中ref count 引用计数器 — 代表有多少文件指向我 — 当为0时就代表文件已经被删掉

软链接文件是一个独立的文件,有自己的inode节点,这个文件数据中保存的是源文件路径,通过保存的路径访问源文件,因此源文件被删除则无法再访问,通过路径将找不到源文件,这时候软链接就会失效。


软链接文件是一个独立的文件有自己的inode节点,文件中保存了源文件路径,通过数据中保存的源文件路径访问源文件


硬链接是文件的一个目录项,与源文件共用同一个inode节点,直接通过自己的inode节点访问源文件(其实本质上来说与源文件没区别)


硬链接被删除,则inode中的链接数-1,并不会直接删除文件数据,而是等链接数为0的时候才会实际删除对应文件的inode,将所占用数据块置为空闲


db78bd9f56c841f9b7dcb9aa52c0a84e.png


相关文章
|
22天前
|
网络协议 安全 Linux
Linux C/C++之IO多路复用(select)
这篇文章主要介绍了TCP的三次握手和四次挥手过程,TCP与UDP的区别,以及如何使用select函数实现IO多路复用,包括服务器监听多个客户端连接和简单聊天室场景的应用示例。
75 0
|
22天前
|
存储 Linux C语言
Linux C/C++之IO多路复用(aio)
这篇文章介绍了Linux中IO多路复用技术epoll和异步IO技术aio的区别、执行过程、编程模型以及具体的编程实现方式。
59 1
Linux C/C++之IO多路复用(aio)
|
6天前
|
安全 Linux 编译器
探索Linux内核的奥秘:从零构建操作系统####
本文旨在通过深入浅出的方式,带领读者踏上一段从零开始构建简化版Linux操作系统的旅程。我们将避开复杂的技术细节,以通俗易懂的语言,逐步揭开Linux内核的神秘面纱,探讨其工作原理、核心组件及如何通过实践加深理解。这既是一次对操作系统原理的深刻洞察,也是一场激发创新思维与实践能力的冒险。 ####
|
9天前
|
网络协议 Linux 调度
深入探索Linux操作系统的心脏:内核与系统调用####
本文旨在揭开Linux操作系统中最为核心的部分——内核与系统调用的神秘面纱,通过生动形象的语言和比喻,让读者仿佛踏上了一段奇妙的旅程,从宏观到微观,逐步深入了解这两个关键组件如何协同工作,支撑起整个操作系统的运行。不同于传统的技术解析,本文将以故事化的方式,带领读者领略Linux内核的精妙设计与系统调用的魅力所在,即便是对技术细节不甚了解的读者也能轻松享受这次知识之旅。 ####
|
5天前
|
缓存 算法 安全
深入理解Linux操作系统的心脏:内核与系统调用####
【10月更文挑战第20天】 本文将带你探索Linux操作系统的核心——其强大的内核和高效的系统调用机制。通过深入浅出的解释,我们将揭示这些技术是如何协同工作以支撑起整个系统的运行,同时也会触及一些常见的误解和背后的哲学思想。无论你是开发者、系统管理员还是普通用户,了解这些基础知识都将有助于你更好地利用Linux的强大功能。 ####
13 1
|
6天前
|
缓存 编解码 监控
深入探索Linux内核调度机制的奥秘###
【10月更文挑战第19天】 本文旨在以通俗易懂的语言,深入浅出地剖析Linux操作系统内核中的进程调度机制,揭示其背后的设计哲学与实现策略。我们将从基础概念入手,逐步揭开Linux调度策略的神秘面纱,探讨其如何高效、公平地管理系统资源,以及这些机制对系统性能和用户体验的影响。通过本文,您将获得关于Linux调度机制的全新视角,理解其在日常计算中扮演的关键角色。 ###
25 1
|
14天前
|
网络协议 Linux 芯片
Linux 内核 6.11 RC6 发布!
【10月更文挑战第12天】
76 0
Linux 内核 6.11 RC6 发布!
|
19天前
|
存储 缓存 固态存储
|
22天前
|
Linux C++
Linux C/C++之IO多路复用(poll,epoll)
这篇文章详细介绍了Linux下C/C++编程中IO多路复用的两种机制:poll和epoll,包括它们的比较、编程模型、函数原型以及如何使用这些机制实现服务器端和客户端之间的多个连接。
19 0
Linux C/C++之IO多路复用(poll,epoll)
|
3月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。