博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
文件空洞产生的原因分析
阅读量:6206 次
发布时间:2019-06-21

本文共 3539 字,大约阅读时间需要 11 分钟。

在文件拷贝时候,scp一个占磁盘空间300G大小(du命令的结果)左右的目录到另外一台机器上,du命令发现该目录占用的磁盘空间变大了,约330多G。为什么会多出来这30G呢?

分析可能原因

一.原机器的block大小为1024k,新机器的block大小为4096k,可能是文件系统block大小引起的。
拷贝的数据文件大概有1000个,文件块的影响也就是1000*4K=4M,而空间增大了约30G,所以不可能是原因一。
二.有些文件存在空洞。空洞scp到新机器后,被填充,占用磁盘空间。
实验:在本机上cp一个有空洞的文件,发现cp前后占用的磁盘大小未变,而scp到另一台机器后,空洞被填满,占用磁盘块变大。
背景知识
ll和du –s读取的文件大小和占用磁盘空间数据来源
struct stat {
dev_t st_dev; /* device */
ino_t st_ino; /* inode */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device type (if inode device) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
自己编写一个小C程序通过fstat函数,取得文件状态,st_size就是ll看到的文件大小,st_blksize是系统每次read,write等i/o的buff大小,通常和文件系统块大小一致,st_blocks是占用的
文件系统的块数,这个块区别以文件系统的块,一般是512字节。Du命令读取st_blocks(du会根据命令参数转换)。
实验过程:创建一个空洞文件file.hole。通过lseek将文件偏移量指针超过文件末尾。
实验机器:block大小为4k.
ll file.hole
-rw-r--r-- 1 zhangfan zhangfan 16394 Jun 22 15:08 file.hole
du -sh file.hole
8.0K file.hole
可以看到,空洞部分没有占用block.
cp一个空洞文件
cp file.hole file.hole.cp
ll file.hole.cp
-rw-r--r-- 1 zhangfan zhangfan 16394 Jul 10 15:51 file.hole.cp
du -sh file.hole.cp
8.0K file.hole.cp
trace一下系统调用的过程
read(3, "abcdefghij\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
write(4, "abcdefghij\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
lseek(4, 4096, SEEK_CUR) = 8192
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
lseek(4, 4096, SEEK_CUR) = 12288
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
lseek(4, 4096, SEEK_CUR) = 16384
read(3, "ABCDEFGHIJ", 4096) = 10
write(4, "ABCDEFGHIJ", 10) = 10
read(3, "", 4096) = 0
close(4) = 0
close(3) = 0
只write了有具体内容的块,空洞没有write,但是lseek是一直在变的,所以cp不会拷贝空洞。
通过看cp的源码,可以看到cp的具体过程:
1、 判断目标文件是否存在,如果存在则清空目标文件,如果不存在则创建目标文件
2、根据目标文件的逻辑块大小,创建拷贝缓冲区
3、判断源文件是否有空洞:文件大小/文件块大小 > 块数 ?
4、读取源文件存放到缓冲区,每次读取一块
5、在第3步中判断,如果存在文件空洞,则对缓冲区数据进行判断,如果缓冲区中的数据均为0,则认为该数据快为空洞,否则认为是正常文件数据
6、如果数据块为空洞,则调用lseek,在目标文件中创建一个空洞;否则拷贝缓冲区数据到目标文件
7、判断本次读取是否读到源文件的文件尾,如果是,则判断本次读取的是否是空洞,如果是空洞则在文件的最后写入""
8、重复1 ~ 7
9、关闭目标文件、源文件
Scp file.hole到另外一台机器
Scp后的文件 ll file.hole
-rw-r--r-- 1 zhangfan zhangfan 16394 Jul 10 15:57 file.hole
du -sh file.hole
20K file.hole
再trace一下scp.
read(3, "abcdefghij\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
write(6, "abcdefghij\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
write(6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
write(6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
write(6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
read(3, "ABCDEFGHIJ", 10) = 10
空洞也被write了,所以du -s会变大 。cp对于稀疏文件的支持(sparse file),是由选项控制的,--sparse=(auto|always|never),默认是支持(auto),具体请man。scp应该不支持稀疏文件,所以scp这样的文件,会被填充成0 ;不过,tar(-S选项)、rsync(也是-S)都是支持的,所有scp的时候可以跟他们配合着用。
 

【本文首发于:
本文转自百度技术51CTO博客,原文链接:http://blog.51cto.com/baidutech/748574
,如需转载请自行联系原作者
你可能感兴趣的文章
深究移动终端大数据:如何做到忠诚度领先?
查看>>
物联网助力 建智慧城市
查看>>
勒索病毒有“解药”?法计算机专家发放解毒软件
查看>>
LinkedIn开源多媒体对象存储数据库Ambry
查看>>
《敏捷可执行需求说明 Scrum提炼及实现技术》—— 3.3 根据预期收益设定反馈目标...
查看>>
RSA:如果你的安全计划的重点是合规性,那就错了!
查看>>
软件测试修炼之道之——重现问题
查看>>
IaaS市场大整合:云用户喜忧参半
查看>>
Android开发规范
查看>>
持续集成服务平台 flow.ci 已支持直接构建码云项目
查看>>
Editor.md v1.3.0 发布,增强快捷键操作等
查看>>
OSC 职位推荐 | 选择易企秀=导师制/硅谷出差/七险一金
查看>>
《深入理解Elasticsearch(原书第2版)》一2.3.2 Mustache模板引擎
查看>>
SurgeMQ —— Go 开发的 MQTT 消息服务器
查看>>
《OSPF和IS-IS详解》一2.7 BGP-IGP的路由交换
查看>>
苹果遭铁杆粉丝吐糟:软件水平江河日下
查看>>
《善用佳软:高效能人士的软件应用之道》一2.1 LibreOffice:开源社区主导的OpenOffice分支...
查看>>
用shell脚本切割nginx日志并压缩
查看>>
《Windows 程序设计(第3版)》——6.7 【实例】窗口查看器
查看>>
联想宣布29亿美元收购摩托罗拉移动
查看>>