linux 稀疏文件(Sparse File)

简介: 稀疏文件,这是UNIX类和NTFS等文件系统的一个特性。开始时,一个稀疏文件不包含用户数据,也没有分配到用来存储用户数据的磁盘空间。当数据被写入稀疏文件时,NTFS逐渐地为其分配磁盘空间。
稀疏文件,这是UNIX类和NTFS等文件系统的一个特性。
开始时,一个稀疏文件不包含用户数据,也没有分配到用来存储用户数据的磁盘空间。当数据被写入稀疏文件时,NTFS逐渐地为其分配磁盘空间。一个稀疏文件有可能增长得很大。
稀疏文件以64KB(不同文件系统不同)为单位增量增长,因此磁盘上稀疏文件的大小总是64KB的倍数。
稀疏文件就是在文件中留有很多空余空间,留备将来插入数据使用。如果这些空余空间被ASCII码的NULL字符占据,并且这些空间相当大,那么,这个文件就被称为稀疏文件,而且,并不分配相应的磁盘块。 
这样,会产生一个问题,文件已被创建了,但相应的磁盘空间并未被分配,只有在有真正的数据插入进来时,才会被分配磁盘块,如果这时文件系统被占满了,那么对该文件的写操作就会失败。为防止这种情况,有两种办法:不产生稀疏文件或为稀疏文件留够空间。
在计算机科学方面,稀疏文件是文件系统中的一种文件存储方式,在创建一个文件的时候,就预先分配了文件需要的连续存储空间,其空间内部大多都还未被数据填充现在有很多文件系统都支持稀疏文件,包括大部分的Unix和NTFS 。
稀疏文件被普遍用来磁盘图像,数据库快照,日志文件,还有其他科学运用上。

1、WINDOWS中的稀疏文件

稀疏文件(Sparse File), 指的是文件中出现大量的0数据,这些数据对我们用处不大,但是却一样的占用我们的空间,针对此,WINNT 3.51中的NTFS文件系统对此进行了优化,那些无用的0字节被用一定的算法压缩起来,使得这些0字节不再占用那么多的空间,在你声明一个很大的稀疏文件时(例如 100GB),这个文件实际上并不需要占用这么大的空间,因为里面大都是无用的0数据,那么,NTFS对稀疏文件的压缩算法可以释放这些无用的0字节空间, 可以说这是对磁盘占用空间以及效率的一种优化,记住,FAT32上并不支持稀疏文件的压缩(至少我在自己机子上测试得出如此结论)


这里,我们将粗略的介绍:

1,如何判断一个磁盘是否支持稀疏文件。
2,如何判断一个文件是否是稀疏文件。
3,如何产生一个稀疏文件。
4,假如系统支持稀疏文件,如何声明这个文件是稀疏文件。



1.1 判断一个磁盘是否是稀疏文件。

我们可以通过一个系统函数GetVolumeInformation 来判断某个磁盘是否支持稀疏文件的压缩。MSDN中的函数原型如下:

GetVolumeInformation

The GetVolumeInformation function retrieves information about a file system and volume that have a specified root directory.

BOOL GetVolumeInformation(
LPCTSTR lpRootPathName,
  LPTSTR lpVolumeNameBuffer,
  DWORD nVolumeNameSize,
  LPDWORD lpVolumeSerialNumber,
  LPDWORD lpMaximumComponentLength,
  LPDWORD lpFileSystemFlags,
  LPTSTR lpFileSystemNameBuffer,
  DWORD nFileSystemNameSize
);

我们只要把查询到的Flag 跟 FILE_SUPPORTS_SPARSE_FILES 位与(&),便可以知道该磁盘是否支持。





这是从我的工具集(toolset)里摘录的例子代码:
  
  
CHAR szVolName[MAX_PATH], szFsName[MAX_PATH]; DWORD dwSN, dwFSFlag, dwMaxLen, nWritten; BOOL bSuccess; HANDLE hFile; bSuccess = GetVolumeInformation(NULL, szVolName, MAX_PATH, &dwSN, &dwMaxLen, &dwFSFlag, szFsName, MAX_PATH); if (!bSuccess) { printf("errno:%d", GetLastError()); return -1; } printf("vol name:%s \t fs name:%s sn: %d.\n", szVolName, szFsName, dwSN); if (dwFSFlag&FILE_SUPPORTS_SPARSE_FILES) { printf("support sparse file.\n"); }else{ printf("no support sparse file.\n"); }
2.1 如何判断一个文件是否是稀疏文件。


  
  我们可以通过 GetFileInformationByHandle()函数来判断一个文件是否是稀疏文件。这是MSDN里面的定义。

The GetFileInformationByHandle function retrieves file information for the specified file.

BOOL GetFileInformationByHandle(
HANDLE hFile,
  LPBY_HANDLE_FILE_INFORMATION lpFileInformation
);
 
例子代码如下:
 
   
   
HANDLE hFile; BY_HANDLE_FILE_INFORMATION stFileInfo; //Open/create file to get the file handle hFile = CreateFile( ); //Get the file information GetFileInformationByHandle(hFile, &stFileInfo); if(stFileInfo.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) { //Sparse file }else{ //Not sparse file }
 
3.1, 如何产生一个稀疏文件并声明该文件是稀疏文件。
   大部分文件,在你改变它的EndOfFile的时候,中间的空白会被操作系统填0,也就是说,如果你用SetFilePointer() 和SetEndOfFile()来
产生一个很大的文件,那么这个文件它占用的是真正的磁盘空间,即使里面全是0,因为系统默认的会在DeviceIoControl()中的ControlCode里用
FSCTL_SET_ZERO_DATA标记,这个标记使得那些文件空洞被0所填充。为了节省磁盘空间,我们必须把一个文件声明为稀疏文件,以便让系统
把那些无用的0字节压缩,并释放相应的磁盘空间,方法如下:
 
  
  
hFile = CreateFile("tmp_file", GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); DWORD dwTemp; DeviceIoControl(hFile, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &dwTemp, NULL); SetFilePointer(hFile, 0x100000, NULL, FILE_BEGIN); WriteFile(hFile, "123", 3, &nWritten, NULL); SetEndOfFile(hFile); CloseHandle(hFile);
注意到FSCTL_SET_SPARSE这个标记了吗?正是这个标记,告诉系统该文件是稀疏文件,如果该文件所在的磁盘支持稀疏
文件的压缩,则系统会释放不必要的0字节空间。你可以用这个方法创建一个100GB得文件试一下(示例里是1M),记得右键看看文件属性
里的‘大小’和占用空间,它被声明为100GB,但是实际上那些0字节基本不占用空间,而你写入的“123”是占用实际的
磁盘空间的。
   注意:在FAT32得磁盘里,因为没有对SPARSE FILE得支持,所以您创建的空洞文件全部被填零,即使你声明它是一个稀疏
文件,也没有任何作用,您声明这个文件多大,它就占用多大的空间。
   另外,如果您编译 DeviceIoControl这个函数出现 "'FSCTL_SET_SPARSE' : undeclared identifier"之类的情况
请这样做:
#include <windows.h>
#define   _WIN32_WINNT         0x0501 
#include <Winioctl.h>

2、Linux文件空洞与稀疏文件

在UNIX文件操作中,文件位移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将延长该文件,并在文件中构成一个空洞。位于文件中但没有写过的字节都被设为0。
如果offset 比文件的当前长度更大,下一个写操作就会把文件“撑大(extend)” 在文件里创造“空洞(hole)”。没有被实际写入文件的所有字节由重复的0 表示。空洞是否占用硬盘空间是由文件系统(file system)决定的。



稀疏文件(Sparse File)
稀疏文件与其他普通文件基本相同,区别在于文件中的部分数据是全0,且这部分数据不占用磁盘空间。
下面是稀疏文件的创建与查看
[root@localhost ~]# dd if=/dev/zero of=sparse-file bs=1 count=1 seek=1024k
[root@localhost ~]# ls -l sparse-file
-rw-r--r-- 1 root root 1048577 Oct 15 17:50 sparse-file
[root@localhost ~]# du -sh sparse-file
8.0K sparse-file
[root@localhost ~]# cat anaconda-ks.cfg >> sparse-file
[root@localhost ~]# du -sh sparse-file
12Ksparse-file
[root@localhost ~]# du -sh anaconda-ks.cfg
12Kanaconda-ks.cfg
[root@localhost ~]#

文件系统存储稀疏文件时,inode索引节点中,只给出实际占用磁盘空间的block号,数据全0,且不占用磁盘空间的文件block并没有物理磁盘block号。

linux稀疏文件Inode数据块存储:
文件空洞部分不占用磁盘空间
文件所占用的磁盘空间仍然是连续的





相关文章
|
1天前
|
Linux
Linux 常用文件查看命令
`cat` 命令用于连接文件并打印到标准输出,适用于快速查看和合并文本文件内容。常用示例包括:`cat file1.txt` 查看单个文件,`cat file1.txt file2.txt` 合并多个文件,`cat &gt; filename` 创建新文件,`cat &gt;&gt; filename` 追加内容。`more` 和 `less` 命令用于分页查看文件,`tail` 命令则用于查看文件末尾内容,支持实时追踪日志更新,如 `tail -f file.log`。
20 5
Linux 常用文件查看命令
|
7天前
|
Linux 网络安全 虚拟化
linux怎么把文件传到docker里面
在现代应用开发中,Docker作为流行的虚拟化工具,广泛应用于微服务架构。文件传输到Docker容器是常见需求。常用方法包括:1) `docker cp`命令直接复制文件;2) 使用`-v`选项挂载宿主机目录,实现数据持久化和实时同步;3) 通过SCP/FTP协议传输文件;4) 在Dockerfile中构建镜像时添加文件。选择合适的方法并确保网络安全是关键。
88 1
|
14天前
|
存储 Linux Shell
Linux|Transfer.sh 轻松实现文件共享
Linux|Transfer.sh 轻松实现文件共享
27 2
Linux|Transfer.sh 轻松实现文件共享
|
18天前
|
Linux Shell
Linux 将所有文件和目录名重命名为小写
Linux 将所有文件和目录名重命名为小写
25 3
|
23天前
|
Linux
Linux文件与目录的日常
目录的切换 一般使用(”pwd“)显示当前所在的目录 比如:当前目录是在home下面的,与用户名相同的文件夹,可以使用(”cd“)命令来切换目录; 进入下载目录(”cd home/a/下载“)这种从给目录开头的一长串路经”叫做绝对路径“; 进入图片目录(”cd .. /图片/“)".."代表当前路径的上级路径,相对于当前的目录而言的”叫做相对路径“,(”.“)代表当前路径; 如果,想快速切换,上一个所在目录可以(”cd - / cd..“); 如果,想快速切换,追原始的目录可以(”cd --“); 查看目录及文件
38 14
|
1月前
|
存储 网络协议 Linux
【Linux】进程IO|系统调用|open|write|文件描述符fd|封装|理解一切皆文件
本文详细介绍了Linux中的进程IO与系统调用,包括 `open`、`write`、`read`和 `close`函数及其用法,解释了文件描述符(fd)的概念,并深入探讨了Linux中的“一切皆文件”思想。这种设计极大地简化了系统编程,使得处理不同类型的IO设备变得更加一致和简单。通过本文的学习,您应该能够更好地理解和应用Linux中的进程IO操作,提高系统编程的效率和能力。
76 34
|
3月前
|
存储 NoSQL Linux
linux积累-core文件是干啥的
核心文件是Linux系统在程序崩溃时生成的重要调试文件,通过分析核心文件,开发者可以找到程序崩溃的原因并进行调试和修复。本文详细介绍了核心文件的生成、配置、查看和分析方法
212 6
|
3月前
|
Ubuntu Linux Go
golang编译成Linux可运行文件
本文介绍了如何在 Linux 上编译和运行 Golang 程序,涵盖了本地编译和交叉编译的步骤。通过这些步骤,您可以轻松地将 Golang 程序编译成适合 Linux 平台的可执行文件,并在目标服务器上运行。掌握这些技巧,可以提高开发和部署 Golang 应用的效率。
375 14
|
3月前
|
存储 NoSQL Linux
linux之core文件如何查看和调试
通过设置和生成 core 文件,可以在程序崩溃时获取详细的调试信息。结合 GDB 等调试工具,可以深入分析 core 文件,找到程序崩溃的具体原因,并进行相应的修复。掌握这些调试技巧,对于提高程序的稳定性和可靠性具有重要意义。
662 6
|
3月前
|
Linux Shell 网络安全
Kali Linux系统Metasploit框架利用 HTA 文件进行渗透测试实验
本指南介绍如何利用 HTA 文件和 Metasploit 框架进行渗透测试。通过创建反向 shell、生成 HTA 文件、设置 HTTP 服务器和发送文件,最终实现对目标系统的控制。适用于教育目的,需合法授权。
103 9
Kali Linux系统Metasploit框架利用 HTA 文件进行渗透测试实验