【Linux】带你深入理解文件系统

目录

文件系统

背景知识

磁盘结构

磁盘的存储结构

磁盘抽象(逻辑,虚拟)结构

BootBlock:

Super block

Data blocks

inode Table

BlcokBitmap

inode Bitmap

Group Descriptor Table 

文件名和inode编号

硬链接和软链接

软链接

硬链接

stderr


文件系统

背景知识

我们讲解文件系统之前还需要说一些背景知识,方便我们快速理解学习文件系统的目的是什么.

1.我们之前一直讲的是open已经打开的文件,及其对应的操作。那没有被打开的文件在哪里呢?

当然是在磁盘,被称作磁盘级文件.


2.我们学习磁盘级文件,侧重点在哪里呢?

        a.单个文件角度:这个文件在哪里,这个文件多大,这个文件的其他属性是什么?

        b.在系统角度:一共有多少个文件?各自属性在哪里,如何快速找到,还可以存储多少个文件?如何让快速找到指定的文件等等

对于b这一系列问题,可以转化成 如何对磁盘文件进行分门别类的存储,以便更好地进行存储。


3.我们想要了解磁盘文件,必须先要了解磁盘.

内存   ---   掉电易失存储介质

磁盘   ---   永久性存储介质  (还有SSD,U盘,光盘,磁带等)

磁盘是一个外设 + 还是我们计算机中唯一一个机械设备。 相比于其它的,这个速度是比较慢的,所以OS一定会有一些提速的方式,后面会说。


磁盘结构

可以先 参考下面的的图片

我们以光盘为例, 我们知道盘面上会存储数据, 但是计算机只认二进制,有什么东西能表示两种状态呢? 磁铁上的南北极!所以向磁盘中写入 本质上就是改变磁盘上的正负性,这个操作是由磁头来完成的.

所以我们的光盘表面上看起来很光滑,实则是由非常多的磁铁组合而成的,微观上来看非常粗糙。


磁盘的存储结构

磁盘上一个盘面那么多数据,那么磁盘是如何知道我想要寻找的数据大致在哪个位置呢?

我们先来了解一下磁盘的存储结构.

 盘面上一个个同心圆便是磁道,每个同心圆被划分的一小段区域叫做扇区扇区是磁盘存储的基本单位。多个盘面半径相同(一个磁盘有多个盘面)的同心圆连起来叫做柱面。

那么在物理上,如何把数据写入指定的扇区呢?

这个问题本质上如何找到一个扇区.

找到一个扇区大概流程如下:

1.首先要先确定在哪一个面上,对应的就是哪一磁头。

2.在哪一个磁道(柱面)

3.在哪一个扇区上.

 以上的寻找方法又叫做CHS寻址.有了它,我们便能找到任意一个扇区,即磁盘上所有扇区都能找到了.


磁盘抽象(逻辑,虚拟)结构

我们小时候应该见过磁带吧,那种一拉很长的那种,那时候英语听力基本用一个录音机,然后放上磁带,练习英语听力,就像下面这样:

一个磁带原本物理结构是圆形结构,我们可以把它拉出来,相当于抽象成了一种线性结构

我们可以把这个卷起来的磁带想象成磁盘的盘片,然后把磁盘的盘面抽象成一种线性结构!

这样把物理结构抽象成这样的线性结构,此时想访问一个扇区,只要找到数组的下标,便可以找到对应的扇区,这样的方法叫做LBA寻址法,然后LBA再通过刚才的CHS就成功的把数据写到了磁盘. 

例如数组有10万个元素,我们可以划分成1-10000为第一个盘面,10001-20000为第二个盘面,以此类推,在第一个盘面中,又划分成0-1000为第一个磁道,1001-2000为第二个磁道,依次推下去,就完成了抽象结构划分.

所以以上的问题都转化成了下面的:

将数据存储到磁盘 ---> 将数据存储到该数组

找打磁盘中特定扇区的位置 ---> 找到数组特定的位置

对磁盘的管理 ---> 对该数组的管理


但是假如一个磁盘500GB大小,直接管理起来非常耗时,而且复杂。所以我们为了方便管理,我们可以对这500G进行划分空间,也就是分区.

 对一个小分区管理好了,其它的分区直接照样用着一套方法即可.

但是100GB还是很大,所以我们还需要继续划分.

此时划分后的每一块叫做块组。每个块组的结构又如下:

它们这些都是什么呢?有什么作用呢,我们来分别讲解:

BootBlock:

先来看第一个BootBlock:

引导块(Boot Block)是特定块组中的第一个块,用于存储 引导加载程序(Bootloader)。引导加载程序是在计算机启动过程中加载并运行操作系统的程序。

引导块的主要目的是启动操作系统,它首先加载操作系统内核或引导程序到内存中,然后传递控制权给内核或引导程序,使其能够继续系统的启动过程。

这个了解一下即可,感兴趣的话可以再深入了解.


Super block

紧接着看一下Super block.

Super block 里面是文件系统的属性信息.

超级块(Super Block)是磁盘块组中的一个特殊数据结构,包含了文件系统的元数据信息,让操作系统能够理解和操作文件系统。它记录了文件系统的整体信息,包括文件系统的类型、大小、块位图和inode位图的位置等重要信息

超级块通常位于块组的起始位置,它在文件系统格式化时被创建并初始化。超级块记录了文件系统的整体信息,以便操作系统可以理解和操作文件系统。

所以Super block相当于是一个文件系统的"总指挥",扮演着一个非常重要的角色.


Data blocks

然后是Data blocks

这里先说一下:虽然磁盘的基本单位是扇区(512字节),但是操作系统(文件系统)和磁盘进行IO的基本单位是4KB(8*512字节).

也就是说,就算OS想从磁盘中读取一个字节的数据,那么最少也必须读取4KB的数据。至于为什么是4KB,这是经过一些科学的计算最终得出的结论,4KB是最合适的.

如果使用512KB,可能会进行更多次数的IO,造成效率降低,而且如果操作系统使用和磁盘一样的大小,万一磁盘基本大小变化了,OS的源代码也需要改变,所以OS有自己一套的规定,这样就完成了软件和硬件的解耦

操作系统与磁盘 IO的基本单位是4KB,这也是一个block大小,所以磁盘也一般叫做块设备。

所以Data blocks可以理解为

1.多个4KB(8*扇区)大小的集合.

linux下文件内容 和 属性是 分开存储的。

2.Data blocks里保存的都是特定文件的内容.


inode Table

接下来说inode Table.

inode是一个大小为128字节的空间,保存的是对应文件的属性

inode Table是该块组内,所有文件的inode空间的集合,需要标识唯一性,每一个inode块,都要有一个inode编号

一般而言,一个文件,只有一个inode,和一个inode编号.

inode编号属于inode,即inode编号是文件的一个属性.

例如我们在Linux下输入ls -li 便可以看到inode编号(黄色框标识的)


BlcokBitmap

再来看BlcokBitmap.

回想刚才的data blocks,有那么多的block,我们怎么知道哪一个被占用,哪一个没有被占用呢?

这个时候便用到了BlockBitmap,它的内部是一个位图,它的每一个比特位和特定的block是一一对应的,对应的bit位位1, 表示该block已经被占用,否则表示空闲可用。

通过块位图,操作系统可以快速了解文件系统上哪些块是可用的,从而进行块的分配和释放。当需要分配一个块给新的文件或目录时,操作系统会查找位图中的空闲位,并将其设置为已分配状态,然后返回该块的地址 给请求的进程。


inode Bitmap

inode Bitmap也是同样的道理.

有那么多的inode,怎么标识哪个被占用,哪个没有被占用呢?还是用inode Bitmap

它的内部也是一个位图,每一个比特位和 特定的inode是一一对应的,如果该比特位为1,说明该inode已经被占用,否则表示空闲可用。

假设有10000+的inode,那么就有10000+的比特位,分别一一对应,然后用0和1表示未被占用和已占用的两种状态.


Group Descriptor Table 

Group Descriptor Table(GDT)叫做块组描述符.

它用来记录这个块组多大,已经使用了多少,有多少个inode,已经占用了多少,还剩多少,一共有多少个block,使用了多少...等等


我们将块组分割成上面的内,并且写入相关的管理数据   ---> 每一个块组都这么干   --->整个分区就被写入了文件系统信息(格式化)! 


一个文件只能有一个inode,和一个inode编号.

我们知道,DataBlocks中是通过每个block存储内容的,那么一个文件 可以有多个block吗?答案是肯定可以的,如果只有一个的话,那么每个文件只能存储4KB大小,这也不切合实际。

在文件属性inode中,会有文件的各种属性,其中就包括了一个blocks数组,里面保存了每个block的位置.

那么如果一个文件特别大,有很多block,blocks数组容不下了,此时如何找到每个block呢?

其实我们要知道,一个block块里不仅可以存储文件内容,也可以存储其它块的块号!

比如blocks[在文件属性inode中]只有15个元素大小,我们可以前12个对应的block[磁盘结构中]存储文件内容后3个对应的block存储的其它block的位置。

一个block是4KB=4096字节大小,存储一个位置只需要4/8字节(32/64位平台),这样一个block就可以存储1000个其它block的位置,如果还是不够,可以取前997个存储内容,后3个存储block的位置,以此类推...

用图大概就是如下这样:

 


文件名和inode编号

通过上面的讲解,我们知道

找到文件:先找到文件inode编号 ---> 找到分区特定的blcok group ---> 找到inode --->相当于知道了属性 --->根据属性便可以找到文件内容.

可问题是我们怎么知道inode编号呢?我们平时用的都是文件名进行操作,比如创建或删除等,所以我们此时需要弄清楚文件名和inode编号之间的关系.

这里提醒一句:linux中,inode属性里面,没有文件名这一说法只根据inode编号辨识文件.

有下面两种场景 :

1.在同一个目录下,可以保存很多的文件,但是文件名不能重复.

2.目录是文件,也有自己的inode,也有自己的data block,但问题是目录data block里面存储的是什么呢?

虽然说linux下是按inode编号来识别文件的,但是我们看到就是文件名啊,这些文件名也一定是被管理的。

这里直接说结论:目录里的data block 存储的是inode 编号 和 文件名的映射关系.

它们互为key值的,也就是说即可用inode编号做key值,也可以用文件名做key值.

这也可以立即为什么创建文件,需要目录有权限,因为目录保存的是文件名与 inode编号映射关系,只有目录有了写权限,,才能将这个映射关系写到磁盘,才能创建成功. 


硬链接和软链接

以上说了这么多,只是为了说明软硬链接,因为只有知道了以上这些知识,这个软硬链接才能更好地理解.

先直接说结论:软硬链接的本质区别是:有没有独立的inode编号!

软硬链接详细的用法后面会说,这里先来看这一种现象:

我们首先创建了三个文件, testLink.txt, testLink1.txt, testLink2.txt.

然后此时我们在软连接一个文件softLink.txt,指令如下:

ln -s testLink.txt soft.txt

然后此时我们再硬链接一个文件hardLink.txt,指令如下:

ln testLink1.txt hardLink.txt

然后此时我们ls -li查看文件的其他属性及inode编号:

我们发现:软链接的文件inode编号不同,硬链接的文件inode编号相同。

软链接有独立的inode --->   软链接是一个独立的文件.

硬链接没有独立的inode --->  硬链接不是一个独立的文件.


软链接

软链接,也称为符号链接,是一种特殊的文件类型。它包含了指向目标文件或目录的路径,类似于Windows中的快捷方式。软链接创建一个新的文件,其中的内容是指向目标文件或目录的路径。

当访问软链接时,实际上是通过路径引导来访问目标文件或目录。软链接可以跨越文件系统边界,在不同的位置创建链接。

指令:

ln -s 目标文件(被链接的文件) 软链接的文件

比如在Linux下,比如有一个文件在特别深的地方。每次执行它需要写很多路径,非常麻烦。

此时我们便可以为这个文件 在一个方便的路径下创建一个软链接的文件,此时每次你在你方便的路径下执行这个软链接文件便可以执行到源文件了.

同样地,在Windows下,比如我们有一个软件在桌面:

 

比如说qq,这个qq其实就是一个软链接的文件,然后我们右击qq,然后点击属性:

 便可以发现源文件其实在和这个桌面毫不相干的一个地方存着,而桌面上的这个qq其实是它的一个软连接,即快捷方式。

硬链接

我们上面知道了,硬链接不是一个独立的文件,因为inode编号一样.

硬链接(Hard Link)是在文件系统中创建的一种链接,将一个文件关联到另一个文件,使得它们共享相同的物理数据块(数据存储内容)。通过硬链接创建的文件实际上是指向相同的inode(索引节点),因此它们在文件系统中被视为相同的文件。

硬链接之间的文件没有所谓的源文件和副本之分,它们都是平等的硬链接文件。即使原始文件被删除,由于硬链接不依赖于原始文件的存在,硬链接本身仍然可以通过其他链接访问,并且数据内容仍然保留在文件系统中,直到所有链接都被删除才会真正释放。

硬链接实则就是在指定的目录下,建立了文件名和指定inode的映射关系,仅此而已!

 我们把这个testLink1删掉了,但是并不影响与之建立硬链接的hardLink.txt,因为inode编号并没有改变,说明文件也没有变化。

但是此时我们发现,第三行原来的数字由2变成1,这个数字叫做硬链接数.就是与某个文件硬链接的文件数量.

这里采用一种叫做引用计数的方法,用来计算和这个文件硬链接的个数count。

当我新增一个硬链接的时候,这个数字count便会+1.

当我删除一个硬链接的时候,并不是把这个文件的inode删除,而是将这个count--,在目录层面,只是将这个文件名与inode编号取消了映射关系。当count == 0的时候,说明此时已经没有文件再关联这个文件了,此时再把这个文件删除,

当我们想取消与某个文件的软硬链接的时候(相当于就是删除了,因为取消了链接这个文件本身就没有意义了),便用到了unlink指令

用法如下:

unlink 文件名

还是刚才的例子,我们想取消软链接,于是我们unlink soft.txt:

 

 取消链接之后,原本的链接文件也被删除了.

硬链接也是如此,就不演示了。但是硬链接也只是删除文件名和inode的映射关系,不会删除文件本身,除非像刚才上面说的与之关联的文件数为0的时候,此时便会彻底删除.


 当我们创建一个目录的时候,发现它的硬链接数是2:

这是哪两个文件与它建立的硬链接呢?

1.自己的目录名 与 inode编号的映射

2.自己目录的内部 . 也与inode有一个映射. 毕竟这个 . 代表了当前路径.

当我们再在这个目录里,创建一个目录:

发现这个硬链接数变成了3,这又是为什么呢?

这是因为每个文件内部都默认有两个隐藏文件, ... ,分别表示当前路径和上一级路径。

dir1的上一级路径就是dir,所以此时又与dir建立了一个硬链接,使得其数量增加了1.

关于文件系统的知识就到这里结束了,其实平常用到的也不多,但是学会这个对以后我们理解文件会有很大的帮助。

这里还有一个上一章小尾巴,就是stderr,我们再这里补充一下:

stderr

我们前面说了stdin,stdout,stderr,我们知道分别是标准输入,标准输出,以及标准错误。

前两个我们都知道,也演示了,分别代表键盘文件,显示器文件。

那这个标准错误是什么呢?

默认情况下,标准输出和标准错误都会输出到终端(通常是命令行终端),这样用户可以同时看到程序的正常输出和错误信息。

通常来说,程序的正常输出应该发送到标准输出流,而程序的错误信息应该发送到标准错误流。这样可以方便地区分正常输出和错误信息,并且可以将它们分别重定向到不同的位置,例如将错误信息保存到日志文件中而不显示在终端上。

我们看下面的代码:

int main()    
{    //stdout -> 1    printf("hello,printf 1\n");    //stderr -> 2    perror("hello,perror 2");    const char* s1 = "hello,write 1\n";    write(1,s1,strlen(s1));    const char* s2 = "hello,write 2\n";    write(2,s2,strlen(s2));    //cout-> 1    std::cout << "hello,cout 1" << std::endl;    //cerr-> 2    std::cerr << "hello,cerr 2" <<std::endl;    return 0;    
} 

分别向fd = 1(标准输出)的文件和 fd = 2(标准错误)的文件输出.我们来运行一下看看结果:

 这些都正常输出到了终端,没有问题。

如果我们此时重定向到log.txt文件,那么这个文件中也会是相同的结果吗?

 当我们把结果重定向到文件中时,终端上直接输出了标准错误,没有标准输出;而显示文件中的内容时,只有标准输出,没有标准错误.

即重定向到文件时,只有标准输出会重定向,而标准错误不会.

这也可以说明:1和2对应的都是显示器文件,但它们两个是不同的,如同认为,同一个显示器文件,被打开了两次.


如果此时我们想把标准输出和错误 分开输出到不同的文件中,该怎么做呢?

./myfile > log.txt 2>err.txt

这句话意思是把./myfile的标准输出 重定向到log.txt文件中,再把2(标准错误) 输出到err.txt中.

此时便有了这两个文件,我们分别查看里面的内容:

 这样便分别输出到了不同的文件中.


或者我就想将标准输出和错误 重定向到一个文件中该怎么做?

./myfile > log.txt 2<&1

前面./myfile > log.txt容易理解,将./myfile 的标准输出 输出到log.txt中.

2>&1: 这是重定向标准错误输出的部分。2表示标准错误输出的文件描述符。&1表示标准输出的文件描述符。因此,2>&1将标准错误输出重定向到与标准输出相同的位置.

此时我们便成功地将标准输入与输出 重定向到同一个文件中了. 


那么如何利用重定向拷贝一份文件呢?

 cat < log.txt > back.txt

这句代码相当于是把log.txt内容先给cat,cat再重定向到back.txt,这样本质上就完成了一次拷贝.

至此所有的内容就结束了.

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

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

相关文章

RocketMQ第一课-快速实战以及集群架构搭建

一、RocketMQ产品特点 1、RocketMQ介绍 ​ RocketMQ是阿里巴巴开源的一个消息中间件&#xff0c;在阿里内部历经了双十一等很多高并发场景的考验&#xff0c;能够处理亿万级别的消息。2016年开源后捐赠给Apache&#xff0c;现在是Apache的一个顶级项目。 ​ 早期阿里使用Act…

设计模式行为型——责任链模式

目录 什么是责任链模式 责任链模式的实现 责任链模式角色 责任链模式类图 责任链模式举例 责任链模式代码实现 责任链模式的特点 优点 缺点 使用场景 注意事项 实际应用 什么是责任链模式 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;又叫职…

【C语言项目】多臂井径电子测井成像项目(一)

目录 1、目的和意义2、本章概述3、串口R2324、OpenGL5、开发环境6、环境配置6.1、VS安装OpenGL6.2、虚拟串口生成工具 7、成品速览参考文献 1、目的和意义 本项目为获取矿藏地层的油气当量和及时精确地测量含油、含气层的压力及温度值的需求&#xff0c;辅助生产管理人员完成对…

警惕!通过谷歌和必应搜索广告传播的新型恶意活动

据观察&#xff0c;一种新的恶意广告活动利用谷歌搜索和必应的广告&#xff0c;以AnyDesk、Cisco AnyConnect VPN和WinSCP等IT工具的用户为目标&#xff0c;诱骗他们下载木马安装程序&#xff0c;目的是入侵企业网络&#xff0c;并可能在未来实施勒索软件攻击。 Sophos在周三的…

最快桌面UI:Siticone Desktop UI 2.1.1 cRACK

富图尔主义控制 80 多个 .NET UI 组件和控件 现代未来 UI/UX 组件 为 Visual Studio 开发做好准备 无限的免费产品支持案例 超轻量和快速性能 广泛可定制和主题化 低资源消耗和占地面积 免版税开发和部署 NET 的最佳 UI 和 UX 库 从最好的图书馆探索无缝流畅的体验 使…

30-使用RocketMQ做削峰处理

1、增加排队功能的思路 在出票模块里,一个消费者拿到了某个车次锁,则该车次下所有的票都由他来出,一张一张的出,知道所有的订单都出完。 2、实现排队出票功能 2.1、 修改发送到MQ消息的内容 修改MQ消息内容,只需要通知出哪天和哪个车次的票(即:组成锁的内容),不需要…

【时频分析,非线性中频】非线性STFT在瞬时频率估计中的应用(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

MATLAB与ROS联合仿真——实例程序搭建思路

一、基础运动控制实例程序搭建思路 1、需要完成的任务&#xff1a; &#xff08;1&#xff09;通过设定小车运动的速度及转角来控制ROS中小车运动。 &#xff08;2&#xff09;通过键盘输入指令控制ROS中小车运动&#xff0c;键盘输入w小车前行&#xff0c;s小车后退&#x…

uniapp 选择城市定位 根据城市首字母分类排序

获取城市首字母排序&#xff0c;按字母顺序排序 <template><view class"address-wrap" id"address"><!-- 搜索输入框-end --><template v-if"!isSearch"><!-- 城市列表-start --><view class"address-sc…

idea 关闭页面右侧预览框/预览条

idea 关闭页面右侧预览框 如图&#xff0c;预览框存在想去除 找了好多方法&#xff0c;什么去掉“setting->appearance里的show editor preview tooltips”的对钩&#xff1b;又或者在该预览区的滚动条上右键&#xff0c;“取消勾选show code lens on scrollbar hover”。都…

《向量数据库指南》——Milvus Cloud2.2.12 易用性,可视化,自动化大幅提升

Milvus Cloud又迎版本升级,三大新特性全力加持,易用性再上新台阶! 近期,Milvus Cloud上线了 2.2.12 版本,此次更新不仅一次性增加了支持 Restful API、召回原始向量、json_contains 函数这三大特性,还优化了 standalone 模式下的 CPU 使用、查询链路等性能,用一句话总…

【MySQL】centos 7下MySQL的环境搭建

从本期博客开始我们正式进入到数据库的学习&#xff0c;在学习数据库时所用到的工具是Linux环境下的MySQL 目录 一、检查环境中是否装有MySQL 二、获取MySQL官方yum源 三、配置MySQL官方yum源 四、一键安装MySQL 五、启动mysql服务 六、登录MySQL 七、修改mysql配置文件…

JS正则表达式:常用正则手册/RegExp/正则积累

一、正则基础语法 JavaScript 正则表达式 | 菜鸟教程 JS正则表达式语法大全&#xff08;非常详细&#xff09; 二、使用场景 2.1、校验中国大陆手机号的正则表达式 正则 /^1[3456789]\d{9}$/解释 序号正则解释1^1以数字 1 开头2[3456789]第二位可以是 3、4、5、6、7、8、…

cnn卷积神经网络(基础)

convolutional neural networks 特征提取&#xff08;卷积、下采样&#xff09;->分类器 &#xff08;全连接&#xff09; 卷积过程 依次进行数乘 &#xff08;每个相同位置上的数字相乘再加和&#xff09; 左右数乘矩阵channel数量要一样&#xff0c;输出得到一个通道 卷…

RabbitMQ 教程 | RabbitMQ 入门

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…

动态线程池问题的解决

项目中需要将线程池也监控管理起来。 于是决定引入了hippo4j&#xff0c;这个引入很简单&#xff0c;官方的例子也很简单&#xff0c;拿过来直接跑。 出现问题了&#xff0c;用的和例子一模一样的&#xff0c;也没什么错&#xff0c;但是就是在服务器的管理控制台上没有找到动态…

Flutter 状态组件 InheritedWidget

Flutter 状态组件 InheritedWidget 视频 前言 今天会讲下 inheritedWidget 组件&#xff0c;InheritedWidget 是 Flutter 中非常重要和强大的一种 Widget&#xff0c;它可以使 Widget 树中的祖先 Widget 共享数据给它们的后代 Widget&#xff0c;从而简化了状态管理和数据传递…

SpringBoot的三层架构以及IOCDI

目录 一、IOC&DI入门 二、三层架构 数据库访问层 业务逻辑层 控制层 一、IOC&DI入门 在软件开发中&#xff0c;IOC&#xff08;Inversion of Control&#xff09;和DI&#xff08;Dependency Injection&#xff09;是密切相关的概念。 IOC&#xff08;控制反转&a…

flask中的蓝图

flask中的蓝图 在 Flask 中&#xff0c;蓝图&#xff08;Blueprint&#xff09;是一种组织路由和服务的方法&#xff0c;它允许你在应用中更灵活地组织代码。蓝图可以大致理解为应用或者应用中的一部分&#xff0c;可以在蓝图中定义路由、错误处理程序以及静态文件等。然后可以…

细讲TCP三次握手四次挥手(一)

计算机网络体系结构 在计算机网络的基本概念中&#xff0c;分层次的体系结构是最基本的。计算机网络体系结构的抽象概念较多&#xff0c;在学习时要多思考。这些概念对后面的学习很有帮助。 网络协议是什么&#xff1f; 在计算机网络要做到有条不紊地交换数据&#xff0c;就必…