上次课上学了lseek这个函数,可以制造出“空洞”文件。演示中,我们发现,用vi或者od命令查看带空洞的文件,空洞部分填满了字符0。于是产生了:
问题一:空洞文件和用字符0写同样长度的文件一样吗?
我们来写一个2000000个’/0’的文件write0.file,再创建一个有长2000000的空洞的文件hole.file。具体方法就不用赘述了(前面直接写,后面lseek)。然后用ls
–ls命令查看(当然也可以用du,不过比较麻烦),发现write0.file的大小为1960k,而hole.file只有8k。所以:
问题一的答案是:不一样。虽然我们用vi或者od读取这两个文件,内容都是显示的一样的,但是这两个文件是有本质的区别的。
问题二:用我们自己写的文件mycp(或者cat),拷贝出两个文件,是什么效果?
用./mycp<write0.file>mycp.write0.file和./mycp<hole.file>mycp.hole.file。再ls
–ls一下发现:拷贝出来的两个文件都是1960k!看来我们的拷贝并没有真正复制到文件全部的信息。
问题二的答案是:结果是一样的。有空洞的文件拷贝完成后,所占磁盘空间变大了。我们写的那个拷贝有bug,所以:
问题三:用shell里面的cp拷贝的结果一样吗?
用cp write0.file cp.write0.file和cp
hole.file cp.hole.file 。再ls –ls一下发现:拷贝出来的两个文件和源文件所占磁盘空间是一样的!应该说,shell里面的那个cp比咱们的要牛一些,它不会丢失文件的信息。man一下cp发现一个参-
-sparse,这个参数专门用来处理文件空洞,它的值有三:auto(默认的,原来有洞,拷贝出来就有洞。原来没洞,拷贝出来也没洞);always(有没有洞都填满0),never(有没有洞都不填)。
答案三:cp比mycp功能强大。于是:
问题四:cp是怎么实现的?
这种问题有个万能解决办法——看源码。
[code=cpp]#if HAVE_STRUCT_STAT_ST_BLOCKS
if (x->sparse_mode == SPARSE_AUTO && S_ISREG (sb.st_mode))
{
/* Use a heuristic to determine whether SRC_PATH contains any
sparse blocks. */
if (fstat (source_desc, &sb))
{
error (0, errno, _("cannot fstat %s"), quote (src_path));
return_val = -1;
goto close_src_and_dst_desc;
}
/* If the file has fewer blocks than would normally
be needed for a file of its size, then
at least one of the blocks in the file is a hole. */
if (S_ISREG (sb.st_mode)
&& sb.st_size / ST_NBLOCKSIZE > ST_NBLOCKS (sb))
make_holes = 1;
}[/code]
关键在最后一个if判断,通过注释可以看出,它通过比较sb.st_size/
ST_NBLOCKSIZE(sb是被拷文件的stat,表示inode里面存放的文件的长度)和ST_NBLOCKS
(sb)(表示所占的实际磁盘大小)。来判断有没有空洞,进行处理。如果有空洞,就跳,如果没有空洞,就写0。具体实现在这里:
[code=cpp] if (make_holes)
{
buf[n_read] = 1; /* Sentinel to stop loop.
*/
/* Find first nonzero *word*, or the word with the sentinel.
*/
ip = (int *) buf;
while (*ip++ == 0)
;
/* Find the first nonzero *byte*, or the sentinel.
*/
cp = (char *) (ip - 1);
while (*cp++ == 0)
;
/* If we found the sentinel, the whole input block was zero,
and we can make a hole.
*/
if (cp > buf + n_read)
{
/* Make a hole. */
if (lseek (dest_desc, (off_t) n_read, SEEK_CUR) < 0L)
{
error (0, errno, _("cannot lseek %s"), quote (dst_path));
return_val = -1;
goto close_src_and_dst_desc;
}
last_write_made_hole = 1;
}
else
/* Clear to indicate that a normal write is needed. */
ip = 0;
}[/code]
问题四答案:嗯!确实比咱们的mycp考虑的周全,但是有没有别的问题呢?
问题五:如果一个文件里面既有空洞,又有人故意写了许多0字符。那么cp还能正确拷贝出源文件的大小吗?
先想一想,如果要我做,我该怎么实现,想来想去发现这个问题好难实现。难处在于就算通过判断文件大小分析出确实存在空洞,但是要找到哪里有空洞,还是需要一个一个读。但是是空洞的地方读出来就是0字符,和专门写的0字符没有办法分辨。看看上面cp的源码,好像也没有考虑这个问题。于是我试验了一下,创建一个文件cp.test,先lseek了1000000然后又继续写了1000000个0字符。先用ls
–ls看看结果,发现它的长度为2000000,占用空间为984k。好,分别用sparse的三个参数拷贝出三个文件:cp.auto;cp.always;cp.never。再查看大小,发现cp.auto和cp.always都是只有8k,cp.never有1960k。没有一个是源程序的大小984k。看来真的没有办法分别空洞和0字符的位置了。
问题五答案:cp也有拷贝不正确的时候。从这里看出,感觉auto和always参数都是一个意思,设计的有些重复了。
得到许多结论:
一、空洞和单纯的0字符并不完全一样,只是空洞被读时会输出0字符。
二、咱们写的那个mycp的程序并不完善,并不能实现cp空洞文件的功能。
三、shell的cp工具也不完善,处理空洞文件时也是有bug的。虽然可以判断出文件有没有空洞,但是不能知道哪里是真正的空洞,哪里是“伪装的空洞”。
四、从cp的源码里面学到sb.st_size和ST_NBLOCKS
(sb),一般来说,这两个东西所代表的是不一样的。
遗留问题:如何正确拷贝出一个既有空洞又有0字符的文件呢?欢迎大家思考回答,有好的想法可以给Torbjorn
Granlund, David MacKenzie, and Jim Meyering(cp的作者)写邮件。
分享到:
相关推荐
编写一个类似cp(1)的程序,它复制包含空洞的文件,但不将字节0写到输出文件中去。
创建一个空洞文件,用于创建一个空洞文件,查看block发现空洞文件占用磁盘大小
类似cp的程序,它复制包含空洞的文件,但不将字节0写到输出文件中去.
编写一个类似于cp l 的程序 它复制包含空洞的文件 但不将字节0写到输出文件中
linux练习文件指针移动及内容填写,使用linux系统调用
并与现场实测结果进行对比,结果表明:探地雷达可以探测到矩形空洞的存在,并能准确识别出充水空洞,但并不能通过反射波中双曲线的弧长来判定空洞的水平范围。应用效果表明探地雷达可有效应用于城市地铁沿线道路空洞的...
内部含有商店免费的sunnyland素材的基本使用,特别的含有空洞骑士的制作,相似度还行(寒假边学边搞出来的),总共有4关包括假骑士一个boss(最后几天写的有点烂)内部还使用了sqlite数据库来保存游戏数据,萌新们...
MATLAB对小于某个面积大小的空洞进行填充,在MATLAB自带的空洞填充代码上加上面积限制
深度学习之空洞卷积原始出处论文,介绍了空洞卷积实现方法以及实现意义。
针对较小的空洞提出了一种新的空洞填充算法。该算法总是先填充那些4邻域像素集中不空的像素大于等于本轮域值的空洞点,并且每填完一遍空洞点之后都重新搜索4邻域像素集中所有像素都不空的空洞点以开始下一轮填充。...
为准确了解雷达波对地下空洞的相应特征,按照与实际尺寸1∶20建立地下空洞模型,并运用Gprmax软件进行正演模拟,通过与现场实测剖面对比分析发现,空洞可造成雷达反射波同相轴不连续,且其波形呈现典型的双曲线形态。...
本插件基于arcgis的模型构建器,可用于图斑的空洞检查。目前较多应用于三调的城镇村图斑空洞检查中,可以很快的提取城镇村图层及城镇村空洞图斑。图斑成果输出在arcgis默认数据库中。后续需要改进可以到评论区中说
Python没有MATLAB中的imfill函数,要实现空洞填充必须自己写函数。文件包含代码以及测试图片,Python3的语法,亲测可用
博客见:https://blog.csdn.net/qq_37534947/article/details/109727232,主要是空洞卷积以及残差网络的代码实现,包含数据集,框架是pytorch
无线传感器网络空洞问题,这是一篇英文论文,综述空洞问题
ArcGIS查找空洞多边形,在arcgis 面要素处理过程,经常遇到空洞面的问题。
针对无线传感器网络中节点因分布不均或能耗而死亡导致覆盖空洞现象问题,提出了一种基于空洞交叉点信息的高效覆盖修补算法(CPA)。该算法依托几何知识,根据基准移动交叉点确定最佳修补位置,通过评估移动节点的...
脊髓空洞症患者中医体质特征调查与分析,杨新宇,刘勇,目地:探索脊髓空洞症的中医体质特征,为脊髓空洞症的防治、养生康复、健康管理提供依据。方法: 本研究采用横断面调查的方法,选�
AutoCAD中利用区域计算实现多边形的重叠与空洞检查,在用cad处理库前数据的时候经常遇到这样的问题,根据论文中提供的思路可以很好的解决这个问题
角色数量:22,素材数量:210,积木数量:1276,音频数量:22 不久前,scratch国际网发布了一款基于空心骑士的游戏,但他从未完成。我在游戏中修复了错误,并对部分进行了完全重新编码,使其运行得更好,同时添加了...