求Win32 API实现Linux fallocate打洞功能的示例代码
Win32 API实现文件打洞(等效Linux
fallocate 打洞功能) Linux下通过fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, 1048576, 2097152)可以在文件中打洞——释放指定偏移开始的磁盘块,同时保持文件总大小不变,将文件转为稀疏文件。在Win32环境中,需要通过**DeviceIoControl**配合两个特定控制码来实现等效功能:
核心步骤
- 标记文件为稀疏文件:通过
FSCTL_SET_SPARSE控制码完成,此操作只需执行一次; - 打洞(释放指定区域磁盘空间):通过
FSCTL_SET_ZERO_DATA控制码,标记指定偏移范围为零数据并释放对应磁盘块,且不会修改文件总大小,完全等效于FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE的行为。
等效示例代码
#include <windows.h> #include <stdio.h> int main() { // 打开目标文件,需要GENERIC_READ | GENERIC_WRITE权限 HANDLE hFile = CreateFileA( "test_sparse_file.dat", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile == INVALID_HANDLE_VALUE) { printf("CreateFile failed, error: %d\n", GetLastError()); return 1; } // 第一步:将文件设置为稀疏文件 DWORD dwBytesReturned; BOOL bResult = DeviceIoControl( hFile, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &dwBytesReturned, NULL ); if (!bResult) { printf("FSCTL_SET_SPARSE failed, error: %d\n", GetLastError()); CloseHandle(hFile); return 1; } // 第二步:执行打洞操作,对应Linux的参数:偏移1MB,长度2MB FILE_ZERO_DATA_INFORMATION zeroData; zeroData.FileOffset.QuadPart = 1048576; // 起始偏移:1MB zeroData.BeyondFinalZero.QuadPart = 1048576 + 2097152; // 结束偏移:1MB+2MB=3MB bResult = DeviceIoControl( hFile, FSCTL_SET_ZERO_DATA, &zeroData, sizeof(zeroData), NULL, 0, &dwBytesReturned, NULL ); if (!bResult) { printf("FSCTL_SET_ZERO_DATA failed, error: %d\n", GetLastError()); CloseHandle(hFile); return 1; } printf("文件打洞操作完成\n"); CloseHandle(hFile); return 0; }
关键说明
FSCTL_SET_SPARSE:将文件转换为稀疏文件,之后文件中连续的零数据块不会占用实际磁盘空间;FSCTL_SET_ZERO_DATA:指定的偏移范围会被标记为零数据,同时系统会释放该范围对应的磁盘块(如果之前有实际数据),且文件总大小保持不变,完全匹配FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE的效果;- 注意:需要确保文件所在的文件系统支持稀疏文件(NTFS支持,FAT32等不支持)。
内容的提问来源于stack exchange,提问作者Cedric Blancher
相关产品推荐
相关产品推荐

