【问题标题】:Is there a way to determine the Physical Sector Size for removable drives with file systems other than NTFS (like FAT16, exFAT...)?有没有办法确定具有 NTFS 以外的文件系统(如 FAT16、exFAT ...)的可移动驱动器的物理扇区大小?
【发布时间】:2014-11-26 18:44:45
【问题描述】:

我需要一个函数来获取所有类型系统驱动器的物理扇区大小,在 Win7 或更高版本中。

这是我直到今天才使用的代码,当时我发现它不适用于我的外部 USB 硬盘(exFAT 文件系统)和我的 USB MP3 播放器 (FAT16)。在这些情况下,函数 DeviceIoControl 失败,我得到异常:“系统错误。代码 50。不支持请求”。但它适用于 NTFS 卷。

function GetSectorSize(Drive:Char):DWORD;
var h:THandle;
    junk:DWORD;
    Query:STORAGE_PROPERTY_QUERY;
    Alignment:STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR;
begin
 result:=0;
 h:=CreateFileW(PWideChar('\\.\'+UpperCase(Drive)+':'),0,FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
 if h=INVALID_HANDLE_VALUE then RaiseLastOSError;
 try
  FillChar(Query,SizeOf(Query),0);
  Query.PropertyId:=StorageAccessAlignmentProperty;
  Query.QueryType:=PropertyStandardQuery;
  if not DeviceIoControl(h,IOCTL_STORAGE_QUERY_PROPERTY,@Query,SizeOf(Query),@Alignment,SizeOf(Alignment),junk,nil) then RaiseLastOSError;
  result:=Alignment.BytesPerPhysicalSector;
 finally
  CloseHandle(h);
 end;
end;

【问题讨论】:

  • 这些其他驱动器是高级格式驱动器吗? fsutil 告诉您有关这些驱动器的哪些信息。
  • 带有 FAT16 的 MP3 播放器我认为它不能是高级格式(它只是一个 U 盘),而 fsutil fsinfo ntfsinfo 不适用于其他 USB 硬盘,因为它是 exFAT,但我认为它可以是高级格式,因为它有 1TB。

标签: delphi filesystems disk


【解决方案1】:

根据 MSDN:

File Buffering

目前大部分的Windows API,如IOCTL_DISK_GET_DRIVE_GEOMETRY和GetDiskFreeSpace,都会返回逻辑扇区大小,但是物理扇区大小可以通过IOCTL_STORAGE_QUERY_PROPERTY控制码获取,相关信息包含在BytesPerPhysicalSector成员中STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR 结构。有关示例,请参阅STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR 的示例代码。 Microsoft 强烈建议开发人员将无缓冲 I/O 与 IOCTL_STORAGE_QUERY_PROPERTY 控制代码报告的物理扇区大小对齐,以帮助确保他们的应用程序为该扇区大小做好准备过渡。

同样的引用也出现在以下 MSDN 文档中:

Advanced format (4K) disk compatibility update

其中包括以下附加信息:

下面的列表总结了作为 Windows 8 和 Windows Server 2012 的一部分提供的新功能,以帮助改善客户和开发人员使用大扇区磁盘的体验。以下是每个项目的更详细说明。
...
• 提供新的 API 来查询物理扇区大小 (FileFsSectorSizeInformation)
...

以下是查询物理扇区大小的方法:
Windows 8 的首选方法

在 Windows 8 中,Microsoft 引入了一个新的 API,使开发人员能够轻松地将 4K 支持集成到他们的应用程序中。与下面讨论的 Windows Vista 和 Windows 7 的旧方法相比,此新 API 支持的方案数量更多。该 API 支持以下调用场景:

•从非特权应用调用
•调用任何有效的文件句柄
•通过 SMB2 调用远程卷上的文件句柄
•简化的编程模型

API 采用新信息类 FileFsSectorSizeInformation 的形式,具有关联的结构 FILE_FS_SECTOR_SIZE_INFORMATION

FILE_FS_SECTOR_SIZE_INFORMATION structure

可以通过以下任一方式查询该信息:

•调用FltQueryVolumeInformationZwQueryVolumeInformationFile,传递FileFsSectorSizeInformation 作为FileInformationClass 的值并传递调用者分配的FILE_FS_SECTOR_SIZE_INFORMATION-结构化缓冲区作为 FileInformation 的值。

•创建具有主要功能代码IRP_MJ_QUERY_VOLUME_INFORMATION 的IRP。

•使用指向 FILE_FS_SECTOR_SIZE_INFORMATION 结构缓冲区的指针调用 FsRtlGetSectorSizeInformation。当从 FsRtlGetSectorSizeInformation 返回此结构时,FileSystemEffectivePhysicalBytesPerSectorForAtomicity 成员将没有由文件系统初始化的值。文件系统驱动程序通常会调用此函数,然后为 FileSystemEffectivePhysicalBytesPerSectorForAtomicity 设置自己的值。

【讨论】:

  • @marusnebunu:您应该扩展该评论​​,因为同一句子的其余部分解释了如何获取物理扇区大小。
  • 是的,我已经做到了(请参阅我的问题中的函数),它适用于 NTFS 文件系统,但不适用于 exFAT 或 FAT16。
  • 不幸的是,FILE_FS_SECTOR_SIZE_INFORMATION 结构从 Windows 8 开始可用。
  • 对。您可以在 Vista 和 Win7 中使用IOCTL_STORAGE_QUERY_PROPERTY。物理扇区大小未在早期版本中公开,您必须使用 IOCTL_DISK_GET_DRIVE_GEOMETRY 或等效项。
【解决方案2】:

您的主要错误是您尝试从卷句柄而不是从底层物理设备 (\\.\PhysicalDriveX) 获取物理扇区大小。设备的物理扇区大小不依赖于 FS,不应与 FS 属性定义的逻辑扇区大小相混淆。

【讨论】:

猜你喜欢
  • 2017-04-10
  • 2012-11-04
  • 2021-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多