浅析空洞文件

1.什么是空洞文件?

在UNIX文件操作中,文件位移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将延长该文件,并在文件中构成一个空洞,这一点是允许的。位于文件中但没有写过的字节都被设为 0。”      --摘自“百度百科”

从上面的描述可以将空洞文件的特点表述为:offset > 实际文件大小。那这又有什么表现和意义呢?我们下面慢慢分析。


2.怎么获得一个空洞文件?

在linux下,利用lseek人为的修改offset可以获得一个空洞文件。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>

#define OFFSET_LENGTH 15000

char buff1[] = "abcdefg";
char buff2[] = "ABCDEFG";

int
main(int argc,char** argv)
{
	int fd = 0;
	
	int buff1Length = strlen(buff1);
	int buff2Length = strlen(buff2);
	
	char* buff3 = (char*)malloc(buff1Length + buff2Length + OFFSET_LENGTH);
	memset(buff3,2,buff1Length + buff2Length + OFFSET_LENGTH);
	
	//create hole file
	if((fd = creat("./hole.f",S_IREAD|S_IWRITE)) < 0)
	{
		perror("create file error!");
	}
	
	printf("fd:%d\n",fd);
	if(write(fd,buff1,buff1Length) != buff1Length)
	{
		perror("write error!");
	}
	
	if(lseek(fd,OFFSET_LENGTH,SEEK_CUR) == -1)
	{
		perror("lseek error!");
	}
	
	if(write(fd,buff2,buff2Length) != buff2Length)
	{
		perror("write error!");
	}
	
	//create nohole file
	if((fd = creat("./nohole.f",S_IREAD|S_IWRITE)) < 0)
	{
		perror("create file error!");
	}
	
	if(write(fd,buff3,strlen(buff3)) != strlen(buff3))
	{
		perror("write error!");
	}
	
	free(buff3);
	
	return 0;
}

上面的程序创建了一个空洞文件和一个同样大小的非空洞文件,接下来我们将以这两个文件作为基础进行空洞文件的分析。


3.空洞文件的表现

空洞文件特点就是offset大于实际大小,也就是说一个文件的两头有数据而中间为空,以‘\0‘填充。那文件系统会不会不做任何处理的将其存放在硬盘上呢?答案是否定的,文件系统没有傻到这种程度,因为这实际是中浪费,也是一种威胁,因为一旦黑客利用这个漏洞不断侵蚀磁盘资源,计算机就崩溃了。所以说,文件系统肯定会做相应的处理,下面我就来验证一下。

用ls来展现两个文件:


我们在用du来展现两个文件(du命令用于报告文件所使用的磁盘空间总量):


可以看到,用ls展现的空洞和非空洞的大小完全相同,而用du命令展现的则有差别,一个占用了8个1024的字节块,而一个占用了16个1024的字节块。这里有个问题,文件大小为15014,算下来最多就15个block,为什么是16个呢?在《APUE》中有这样的解释:"文件系统使用了若干块以存放指向实际数据块的各个指针"。

为什么会这样呢?原因是ls展现的文件的逻辑大小,也就是文件在文件系统表现出来的大小,而du展现的是文件物理大小,也就是文件在磁盘上实际所占的block数。所以说,空洞文件在文件系统表现的还是和普通文件一样的,但是实际上文件系统并没有给他分配所表现出来的那么多空间,只是存放了有用的信息。

接下俩我们再来看一个现象:

首先我们用cat来输出空洞文件中内容,然后重定向到一个新的文件中:


我们再来用cp去复制一个文件:


可以看到,用cat得到的文件,文件实际占用的block增加了,而cp的没有。那是因为cat在复制空洞文件时会将空洞补齐,将空洞填以0,因为cat命令就是简单的read和write的操作,read在遇到空洞时读出0,write则写入0,这时文件就变成了非空洞文件,而cp在复制文件时不会,cp命令会去判断文件是否有空洞,如果有,则会调用lseek进行空洞的模拟,所以还是会保持和源文件的一致性。


4.空洞文件有什么用?

空洞文件作用很大,例如迅雷下载文件,在未下载完成时就已经占据了全部文件大小的空间,这时候就是空洞文件。下载时如果没有空洞文件,多线程下载时文件就都只能从一个地方写入,这就不是多线程了。如果有了空洞文件,可以从不同的地址写入,就完成了多线程的优势任务。

感觉这并不是空洞文件的全部作用,后续将进行补充。。。。



  • 17
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值