当前位置: 首页 > 科技观察

0.2秒居然复制了100G文件?_0

时间:2023-03-12 07:24:27 科技观察

图来自抱图网cp引发的思考。用ls查看文件,发现文件确实是100G。sh-4.4#ls-lh-rw-r--r--1rootroot100GMar612:22test.txt但是为什么复制这么快?sh-4.4#timecp./test.txt./test.txt.cpreal0m0.107suser0m0。008ssys0m0.085sSATA机械盘的写入能力可以达到150M/s(大部分机械盘达不到这个值),已经算是很不错了。一般情况下,复制一个100G的文件(100G/150M/s)至少需要682秒,也就是11分钟。实际情况是cp在一秒之内完成了工作。我惊呆了。为什么?更奇怪的是:他的文件系统只有40G,里面怎么会有100G的文件?我的同事发给我这里,看看这个奇怪的问题。①我让他先用du命令看文件,结果只有2M,根本不是100G。这是怎么回事?sh-4.4#du-sh./test.txt2.0M./test.txt然后看stat命令显示的信息:sh-4.4#stat./test.txtFile:./test.txtSize:107374182400Blocks:4096IOBlock:4096regularfileDevice:78h/120dInode:3148347Links:1Access:(0644/-rw-r--r--)Uid:(0/root)Gid:(0/root)Access:2021-03-1312:22:00.888871000+0000修改:2021-03-1312:22:46.562243000+0000Change:2021-03-1312:22:46.562243000+0000Birth:-stat命令输出说明:Size为107374182400(知识点:单位为byte),即100G。Blocks的指标显示为4096(知识点:一个Block的单位固定为512字节,也就是一个扇区的大小),这里表示为2M。要点:Size表示文件大小,也是大多数人看到的大小。块表示实际占用的物理空间。有同事问:“文件大小和实际占用的物理空间不是一个概念!这是为什么呢?”“看来还得深入到文件系统里面去了解一下,来,我给你解释一下。”文件系统文件系统听起来很高端。在普通话中,它只是一个存储数据的容器。本质上,它与你的手提箱或仓库没有什么不同,只不过文件系统存储的是数字产品。我有一个视频文件,我把这个视频放在这个文件系统里,下次来拿的时候,我要拿到我完整的视频文件数据,这个就是文件系统,对外提供访问服务。现实接入场景:比如去火车站使用寄存服务寄存行李,是否需要登记一些个人信息?对,至少你的名字必须写上。你也可能会得到一个让你挂在手上的标志。这个东西是给每一个行李做标记。取行李的时候要报名字,有牌子的就把牌子给他,然后工作人员就可以到特定的位置找你的行李了。要点:保存时一定要记录一些关键信息(记录ID,身份证),以便取出时可以正确定位。①文件系统回到我们的文件系统,对比上面的行李访问行为,我们可以做一个简单的类比:注册名就是在文件系统中记录文件名,生成的品牌就是元数据索引,你的行李就是文件存储room就是磁盘(容纳东西的物理空间)管理员的整套运行机制就是文件系统上的对应不是很严格,只是为了帮助大家了解文件系统,让大家知道文件系统其实是一个很简单的东西,想法来源于生活。②空间管理现在想想文件系统是如何管理空间的?如果给你一个连续的大磁盘空间,你将如何使用这个空间?一个直观的想法,我把所有传入的数据都放进去。这种方法实现起来非常简单,而且是眼前最简单的方法,以后却是最麻烦的方法。因为会造成很多空洞,明明还有很多空间位置,但是因为整体太大,形状不合适(数据大小),放不下任何地方。因为你要放满空间。如何提高?有的人会想,既然整个放不进去,那就剁碎吧。这里塞一点,那里塞一点,就进去了。是的,这个想法是完全正确的。改进的方法是切分,按照一定的粒度对空间进行切分。每个小粒度的物理块被命名为Block,每个块的大小一般为4K。自然,用户数据在文件系统中存储时,必须分段存储在磁盘的各个角落。图标标签表示完整对象的块序号,用于还原对象。那么还有一个问题:你直接切块,拿到文件数据的时候,还得把它们组合起来。因此,必须有一个表来记录所有块在文件中的位置。该表被文件系统称为索引节点。写入文件的过程如下:先写入数据:数据先按照块粒度存储在磁盘的各个位置。然后写元数据:然后保存Block所在的各个位置,也就是inode(我用一本书来表示)。读取文件的过程是:首先读取inode,找到每个block所在的位置。然后读取数据,构造一个完整的文件,交给用户。inode/block的概念不错,现在来看看inode,直观感受:这个inode有文件元数据和一个Block数组(长度为15),数组中的前两项分别指向Block3和Block11,说明数据在这两个存储在一个块中。你肯定会发现块数组只有15个元素,每个块是4K。难道一个文件最大只能15*4K=60K?这绝对不可能!最简单的方法是:将块数组的长度给Expand!比如我们要让文件系统最大支持100G的文件,那么Block数组就需要这么长:(100*1024*1024)/4=26214400。Block数组中每一项为4字节,需要(26214400*4)/1024/1024=100M。为了支持100G的文件,我们的Block数组本身必须是100M!每个文件都是如此!哪怕这个文件只有1K!把这15个slot分成4个不同的类别:前12个slot(也就是0-11)我们成为directindex的第13个位置,我们称之为一级索引的第14个位置,我们称之为第15个位置二级索引称为三级索引直接索引:可以存储12个块号,每个块4K,也就是48K。也就是说,对于48K以内的文件,前12个槽位可以存放的数字完全hold住。一级索引:也就是说,这里存储的数字指向的块也存储了块号,里面的数字指向用户数据。一个块4K,每个元素为4字节,即可以存储1024个编号位置。因此,主索引可以寻址4M(1024*4K)空间。二级指标:二级指标只是在一级指标的基础上多了一个层次。转换时,有4M空间存放用户数据号。所以二级索引可以寻址4G(4M/4*4K)空间。三级索引:三级索引是在二级索引的基础上增加了一个级别,即有4G的空间来存放用户数据的块号。所以二级索引可以寻址4T(4G/4*4K)空间。所以,在这个文件系统(比如ext2)上,通过这种间接块索引的方式,最大支持的文件大小=48K+4M+4G+4T,约等于4T。这种多级索引寻址的性能如何?不超过12个数据块的小文件寻址最快。理论上访问文件中的任何数据只需要两次磁盘读取,一次读取索引节点,一次读取数据块。访问大文件中的数据最多需要五个磁盘读取操作:索引节点、一级间接寻址块、二级间接寻址块、三级间接寻址块和数据块。为什么cp这么快?接下来我们要写一个奇怪的文件,这个文件很大,但是真正的数据只有8K:[0,4K]处有4K数据,还有[1T,1T+4K]处没有数据中间4K的数据,这样的文件怎么写入硬盘?此时创建一??个文件并分配一个inode。在[0,4K]位置写入4K数据,此时只需要一个block,将这个数写入block[0]并保存。在[1T,1T+4K]位置写入4K数据。这时候需要分配一个block,因为这个位置已经落入了只能由三级索引表示的空间,所以需要分配3个索引block。.写入后,关闭文件。实际存储如图:此时我们的文件看起来是一个非常大的文件,大小等于1T+4K,但里面的实际数据只有8K,位置是[0,4K],[1T,1T+4K].由于没有写入数据的地方不需要分配物理块,实际占用的物理空间只有8K。重要提示:文件大小只是inode中的一个属性。实际占用的物理空间取决于用户数据中放置了多少块。无需分配未写入数据的物理块。这样的文件实际上是一个稀疏文件,它的逻辑大小不等于实际的物理空间。所以我们在使用cp命令复制这样一个文件的时候,一定要快速完成。那么,我们再进一步思考一下,为什么文件系统可以做到这一点呢?首先,最重要的是将磁盘空间划分成离散的、固定长度的块进行管理。然后,可以通过inode找到所有离散数据(保存所有索引)。最后,实现索引块和数据块空间的后分配。这三点是进步的。后记这个小知识我跟朋友讲了一个小时,看他感动得流泪的表情,我想他学会了飞,很满足。是我想太多了吗?你没有叫我吃午饭。作者:奇亚编辑:陶家龙来源:转载自公众号奇亚云存储(ID:qiyacloud)