CP命令引发的思考

转自:OSC开源社区

  今天同事用 cp 命令,把他给惊到了!

背景是这样的:他用 cp  拷贝了一个 100 G的文件,竟然一秒不到就拷贝完成了!

用 ls  看一把文件,显示文件确实是 100 G。

sh-4.4# ls -lh
-rw-r--r-- 1 root root 100G Mar  6 12:22 test.txt

但是copy起来为什么会这么快呢?

sh-4.4# time cp ./test.txt ./test.txt.cpreal 0m0.107s
user 0m0.008s
sys 0m0.085s

一个 SATA 机械盘的写能力能到 150 M/s (大部分的机械盘都是到不了这个值的)就算非常不错了,正常情况下,copy 一个 100G 的文件至少要 682 秒 ( 100 G/ 150 M/s ),也就是 11 分钟。

实际情况却是 cp 一秒没到就完成了工作,惊呆了,为啥呢?

更诡异的是:他的文件系统只有 40 G,为啥里面会有一个 100 G的文件呢?

同事把我找来,看看这个诡异的问题。

分析文件

我让他先用 du 命令看一下,却只有 2M ,根本不是100G,这是怎么回事?

sh-4.4# du -sh ./test.txt
2.0M ./test.txt

再看 stat 命令显示的信息:

sh-4.4# stat ./test.txtFile: ./test.txtSize: 107374182400 Blocks: 4096       IO Block: 4096   regular file
Device: 78h/120d Inode: 3148347     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2021-03-13 12:22:00.888871000 +0000
Modify: 2021-03-13 12:22:46.562243000 +0000
Change: 2021-03-13 12:22:46.562243000 +0000Birth: -

stat 命令输出解释:

  1. Size 为 107374182400(知识点:单位是字节),也就是 100G ;

  2. Blocks 这个指标显示为 4096(知识点:一个 Block 的单位固定是 512 字节,也就是一个扇区的大小),这里表示为 2M;

划重点

  • Size 表示的是文件大小,这个也是大多数人看到的大小;

  • Blocks 表示的是物理实际占用空间

同事问道:文件大小和实际物理占用,这两个竟然不是相同的概念 !为什么是这样?   

“看来,我们必须得深入文件系统才能理解了,来,我给你好好讲讲。”

文件系统

文件系统听起来很高大上,通俗话就用来存数据的一个容器而已,本质和你的行李箱、仓库没有啥区别,只不过文件系统存储的是数字产品而已。

我有一个视频文件,我把这个视频放到这个文件系统里,下次来拿,要能拿到我完整的视频文件数据,这就是文件系统,对外提供的就是存取服务

现实的存取场景

例如你到火车站使用寄存服务:

存行李的时候,是不是要登记一些个人信息?对吧,至少自己名字要写上。可能还会给你一个牌子,让你挂手上,这个东西就是为了标示每一个唯一的行李。

0852a1519afc33e24b9c92180b71ccfd.gif

取行李的时候,要报自己名字,有牌子的给他牌子,然后工作人员才能去特定的位置找到你的行李

4401aad0ebef4af0973dfb9be7be30cb.gif

划重点:存的时候必须记录一些关键信息(记录ID、给身份牌),取的时候才能正确定位到。

文件系统

回到我们的文件系统,对比上面的行李存取行为,可以做个简单的类比;

  1. 登记名字就是在文件系统记录文件名;

  2. 生成的牌子就是元数据索引;

  3. 你的行李就是文件;

  4. 寄存室就是磁盘(容纳东西的物理空间);

  5. 管理员整套运行机制就是文件系统;

上面的对应并不是非常严谨,仅仅是帮助大家理解文件系统而已,让大家知道其实文件系统是非常朴实的一个东西,思想都来源于生活。

空间管理

现在思考文件系统是怎么管理空间的?

如果,一个连续的大磁盘空间给你使用,你会怎么使用这段空间呢?

直观的一个想法,我把进来的数据就完整的放进去。

39958635cb30e31bff4d6a38c869e37e.gif

这种方式非常容易实现,属于眼前最简单,以后最麻烦的方式。因为会造成很多空洞,明明还有很多空间位置,但是由于整个太大,形状不合适(数据大小),哪里都放不下。因为你要放一个完整的空间。

怎么改进?有人会想,既然整个放不进去,那就剁碎了呗。这里塞一点,那里塞一点,就塞进去了。

对,思路完全正确。改进的方式就是切分,把空间按照一定粒度切分。每个小粒度的物理块命名为 Block,每个 Block 一般是 4K 大小,用户数据存到文件系统里来自然也是要切分,存储到磁盘上各个角落。

ef040d4b2238b31962ae4287f1f50d09.gif

图示标号表示这个完整对象的 Block 的序号,用来复原对象用的。

随之而来又有一个问题:你光会切成块还不行,取文件数据的时候,还得把它们给组合起来才行。

所以,要有一个表记录文件对应所有 Block 的位置,这个表被文件系统称为inode

写文件的流程是这样的:

  1. 先写数据:数据先按照 Block 粒度存储到磁盘的各个位置;

  2. 再写元数据:然后把 Block 所在的各个位置保存起来,即inode(我用一本书来表示);

bed2193b6e29879a47265af42b48e387.gif

读文件流程则是:

  1. 先读inode,找到各个 Block 的位置;

  2. 然后读数据,构造一个完整的文件,给到用户;

31eba3db808b4eb9e3ff60e7f20f9821.gif

inode/block 概念

好,我们现在来看看inode,直观地感受一下:

beecc9b4bc04355bebe0dd21976ba5b1.png

这个inode有文件元数据和Block数组(长度是15),数组中前两项指向Block 3和Block 11,表示数据在这两个块中存着。 

你肯定会意识到:Block数组只有15个元素,每个Block是4K, 难道一个文件最大只能是 15 * 4K =  60 K ?  

这是绝对不行的! 

最简单的办法就是:把这个Block数组长度给扩大!

比如我们想让文件系统最大支持100G的文件,Block数组需要这么长:

(100*1024*1024)/4 = 26214400

Block数组中每一项是4个字节,那就需要(26214400*4)/1024/1024 = 100M 

为了支持100G的文件,我们的Block数组本身就得100M ! 

并且对每个文件都是如此 !即使这个文件只有1K! 这将是巨大浪费!

肯定不能这么干,解决方案就是间接索引,按照约定,把这 15 个槽位分作 4 个不同类别来用:

  1. 前 12 个槽位(也就是 0 - 11 )我们成为直接索引

  2. 第 13 个位置,我们称为 1 级索引

  3. 第 14 个位置,我们称为 2 级索引

  4. 第 15 个位置,我们称为 3 级索引

c8c0cf5392ea0f73fbd9f6ac4549fe28.png

直接索引:能存 12 个 block 编号,每个 block 4K,就是 48K,也就是说,48K 以内的文件,前 12 个槽位存储编号就能完全 hold 住。

一级索引

也就是说这里存储的编号指向的 block 里面存储的也是 block 编号,里面的编号指向用户数据。一个 block  4K,每个元素 4 字节,也就是有 1024 个编号位置可以存储。

所以,一级索引能寻址 4M(1024 * 4K)空间 。

843a6ed691832ad7da4f09d5f2d26ae8.png

二级索引

二级索引是在一级索引的基础上多了一级而已,换算下来,有了 4M 的空间用来存储用户数据的编号。所以二级索引能寻址 4G (4M/4 * 4K) 的空间。

343446a4170a08dbce3881323b595839.png

三级索引

三级索引是在二级索引的基础上又多了一级,也就是说,有了 4G 的空间来存储用户数据的 block 编号。所以二级索引能寻址 4T (4G/4 * 4K) 的空间。

c051ac60c593ec3e7bebf20665e04bdf.png

所以,在这种文件系统(如ext2)上,通过这种间接块索引的方式,最大能支撑的文件大小 = 48K + 4M + 4G + 4T ,约等于 4 T。

这种多级索引寻址性能表现怎么样?

在不超过 12 个数据块的小文件的寻址是最快的,访问文件中的任意数据理论只需要两次读盘,一次读 inode,一次读数据块。

访问大文件中的数据则需要最多五次读盘操作:inode、一级间接寻址块、二级间接寻址块、三级间接寻址块、数据块。

为什么cp那么快?

接下来我们要写入一个奇怪的文件,这个文件很大,但是真正的数据只有8K:

在[0,4K]这位置有4K的数据

在[1T , 1T+4K] 处也有4K数据

中间没有数据,这样的文件该如何写入硬盘?

  1. 创建一个文件,这个时候分配一个 inode;

  2. 在 [ 0,4K ] 的位置写入 4K 数据,这个时候只需要 一个 block,把这个编号写到 block[0] 这个位置保存起来;

  3. 在 [ 1T,1T+4K ] 的位置写入 4K 数据,这个时候需要分配一个 block,因为这个位置已经落到三级索引才能表现的空间了,所以需要还需要分配出 3 个索引块;

  4. 写入完成,close 文件;

实际存储如图

ed930e215a04e32afc81860a598246d1.png

这个时候,我们的文件看起来是超大文件,size 等于 1T+4K ,但里面实际的数据只有 8 K,位置分别是  [ 0,4K ] ,[ 1T,1T+4K ]。 

由于没写数据的地方不用分配物理block块,所以实际占用的物理空间只有8K。

重点:文件 size 只是 inode 里面的一个属性,实际物理空间占用则是要看用户数据放了多少个 block ,没写数据的地方不用分配物理block块。

这样的文件其实就是稀疏文件, 它的逻辑大小和实际物理空间是不相等的。 

所以当我们用cp命令去复制一个这样的文件时,那肯定迅速就完成了。

总结

好,我们再深入思考下,文件系统为什么能做到这一点?

  1. 首先,最关键的是把磁盘空间切成离散的、定长的 block 来管理;

  2. 然后,通过 inode 能查找到所有离散的数据(保存了所有的索引);

  3. 最后,实现索引块和数据块空间的后分配;

这三点是层层递进的。


推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

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

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

相关文章

安装windows XP或者2003时提示找不到硬盘驱动器的解决办法(总结)转载

(本文属于转载) 由于SATA接口在近年才推出,Windows XP问世的时候,还没有它,所以安装Windows XP时,需要调用SATA驱动程序,而你又没有提供相应的驱动,就会出现无法识别硬盘的错误。 不…

C宏定义注意事项

1、带参数的宏与函数的优缺点 2、宏定义一个函数时&#xff0c;需要注意每个参数都需要用括号括起来。 如&#xff1a;#define Min(a,b) ((a)<(b)?(a):(b)) 3、宏定义一年中的秒数 #define SECONDE_OF_YEAR 606024365UL &#xff08;√&#xff09; #define SECONDE_OF_YE…

不要再来北上广深了

大家好&#xff0c;我是写代码的篮球球痴最近我们的一个离职群里面讨论一个问题&#xff0c;就是在北上广深工作的性价比问题&#xff0c;我有几个同事这样描述。一线城市确实会遇到一些机会&#xff0c;也有可能会遇到一些改变命运的机会。不过对于生活来说&#xff0c;一线城…

mogndb 慢查询

0 摘要 在MySQL中&#xff0c;慢查询日志是经常作为我们优化查询的依据&#xff0c;那在MongoDB中是否有类似的功能呢&#xff1f;答案是肯定的&#xff0c;那就是开启Profiling功能。该工具在运行的实例上收集有关MongoDB的写操作&#xff0c;游标&#xff0c;数据库命令等&a…

Linux命令中正则表达式的运用

一、正则表达式简介 事实上&#xff0c;正则表达式不仅适用于linux&#xff0c;多种编程语言中也可以使用到它&#xff0c;因为它实际上是人们对于某种规律的表达方式。 如果要把他的所有应用都讲上的话那这篇文章会变的太长以至于无法阅读&#xff0c;我只介绍他在linux下和几…

程序的内存分配模式(堆栈以及静态存储区,文字常量区,代码区)

程序的内存分配模式 一个由 C/C编译的程序占用的内存分为以下几个部分&#xff1a; 1、栈区&#xff08; stack &#xff09;—由编译器自动分配释放&#xff0c;存放函数的参数值&#xff0c;局部变量的值 等。其操作方式类似于数据结构中的栈。 2、堆区&#xff08; heap&a…

稚晖君教你制作全球最迷你的自平衡机器人

摘要&#xff1a;Nano是一个小巧可爱的机器人&#xff0c;身高大约10公分&#xff0c;特点是平衡感好&#xff0c;长得很白以及善于卖萌。作为全球最迷你的自平衡机器人&#xff0c;Nano身材虽小&#xff0c;但配置有丰富的传感器—陀螺仪&#xff0c;超声波&#xff0c;Motion…

9.13作业

2、python test.py执行的三个阶段是什么&#xff1f;在哪个阶段识别文件内的python语法&#xff1f; 先运行python解释器&#xff0c;将python文件从硬盘读取到内存&#xff0c;解释执行内存读取的代码&#xff0c;开始识别python语法。 在第3个阶段识别文件内的python语法 3、…

tomcat 6.0环境, 网页超链接,文件下载另存为时,不能识别msi文件类型,另存为只能选htm和所有文件。...

问题: tomcat 6.0环境&#xff0c; 网页超链接&#xff0c;文件下载另存为时&#xff0c;不能识别msi文件类型&#xff0c;另存为只能选htm和所有文件。 解决办法:在 ...\Tomcat 6.0\conf 文件夹下的 web.xml 文件中添加以下类型声明:<mime-mapping><extension>msi…

ARM不同位数系统int字节数区别

32位和64位系统区别及int字节数 一&#xff09;64位系统和32位有什么区别&#xff1f; 1、64bit CPU拥有更大的寻址能力&#xff0c;最大支持到16GB内存&#xff0c;而32bit只支持4G内存 2、64位CPU一次可提取64位数据&#xff0c;比32位提高了一倍&#xff0c;理论上性能会…

我的广州大伯

2021年11月24日我正在办公室和同事调试项目&#xff0c;突然接到我婶的微信语音电话&#xff0c;我婶说广州的大伯过世了&#xff0c;他们现在正在去大伯家的路上。我大伯是爷爷奶奶最大的儿子&#xff0c;爷爷奶奶在世时&#xff0c;家里的很多事情&#xff0c;都会和大伯商量…

VUE 入坑系列 一 双向绑定

html代码<div id"app"><p>{{message}}</p><span>message1</span> <input v-model"message"><span>message2</span> <input v-model"message"></div> View Codejavascript代码var …

semihost/ITM机制浅析以及使用JLINK通过ITM调试stm32单片机

使用ITM机制实现调试stm32单片机&#xff0c;实现printf与scanf。 ITM简介 ITM机制是一种调试机制&#xff0c;是新一代调试方式&#xff0c;在这之前&#xff0c;有一种比较出名的调试方式&#xff0c;称为半主机&#xff08;semihosting&#xff09;方式。 在pc上编写过C语…

spring+ibatis配置

spring-dao.xml配置 <bean id"sqlMapClient" class"org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name"configLocation" value"classpath:/sql-map-config.xml"/> <property…

5毛钱搞一个2.4GHz射频信号探测器

射频电子领域神秘而又朦胧&#xff0c;今天我们通过一个小小的射频检波电路来体验一下射频世界的魅力。实验目的制作一个 2.4 GHz 射频信号探测器&#xff0c;电路简单总成本不到 5 毛钱。该电路在靠近 2.4 GHz 无线信号时 LED 灯会闪烁。这是我用制作好的 2.4 GHz 射频信号靠近…

华为宣布:免费培养8000名嵌入式开发者!学习免费!实践免费!辅导免费!

真正的5G时代&#xff0c;万物互联各行各业都离不开智能物联网技术物联网 (IoT) 设备会生成海量数据通过分析这些数据可以提供业务洞察力优化业务决策&#xff0c;实现流程自动化也由于物联网的迅速兴起&#xff0c;专业性人才稀缺各阶层课程层出不穷&#xff0c;开发者眼花缭乱…

关于××× 相关收集资料

1、服务&#xff1a; 那要建立一个必需要什么条件呢&#xff1f; 第一&#xff1a;服务器要有一个固定的外网IP地址。 第二&#xff1a;服务器至少要有两张网卡&#xff0c;来接口和内部网的通信。 当有了这样的条件&#xff0c;我们就可以来建立一台服务器了。转载于:https://…

现在不要着急买房

我写这篇文章&#xff0c;是因为确实最近有人向我咨询买房的事&#xff0c;今天抽空想聊下这方面的事&#xff0c;如果观点不正确&#xff0c;欢迎评论说出你的想法。是前天&#xff0c;我一个同学咨询我买房的事情。我也直接说了&#xff0c;最近两年&#xff0c;把钱放在口袋…

解决vlc-android播放http视频退出问题

之前用vlc-android播放http视频,程序就自动退出了,尝试用ndk-gdb调试,但是一调试,就报 /home/administrator/code/vlc-android/extras/package/android/vlc-android/obj/local/armeabi/gdb.setup:4: Error in sourced command file:Remote communication error: Connection res…

受保护的属性无法直接读取

转载于:https://www.cnblogs.com/xiaobiaomei/p/9645795.html