DeviceIoControl返回意外的物理扇区大小。

4

我使用DeviceIoControl来返回物理磁盘扇区的大小。一直以来它都返回512字节,直到最近开始返回4096字节。检查结果中的STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR,我发现逻辑字节大小和物理字节大小已经交换了位置 - 磁盘扇区的逻辑字节大小不应该始终大于或等于物理扇区大小吗?

#include <Windows.h>
#include <iostream>
#include <Windows.h>

#pragma comment(lib, "Kernel32.lib")

int main()
{
    HANDLE hDevice;

    char cDisk = 'c';   // Get metadata about the C:\ disk

    // Build the logical drive path and get the drive device handle
    std::wstring logicalDrive = L"\\\\.\\";
    wchar_t drive[3];
    drive[0] = cDisk;
    drive[1] = L':';
    drive[2] = L'\0';
    logicalDrive.append(drive);

    hDevice = CreateFile(
        logicalDrive.c_str(),
        0, 
        0,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);

    if (hDevice == INVALID_HANDLE_VALUE)
    {
        std::cerr << "Error\n";
        return -1;
    }   

    // Now that we have the device handle for the disk, let us get disk's metadata
    DWORD outsize;
    STORAGE_PROPERTY_QUERY storageQuery;
    memset(&storageQuery, 0, sizeof(STORAGE_PROPERTY_QUERY));
    storageQuery.PropertyId = StorageAccessAlignmentProperty;
    storageQuery.QueryType  = PropertyStandardQuery;

    STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment = {0};
    memset(&diskAlignment, 0, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR));

    if (!DeviceIoControl(hDevice, 
        IOCTL_STORAGE_QUERY_PROPERTY, 
        &storageQuery, 
        sizeof(STORAGE_PROPERTY_QUERY), 
        &diskAlignment,
        sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), 
        &outsize,
        NULL)
        )
    {
        std::cerr << "Error\n";
        return -1;
    }

    std::cout << "Physical sector size: " diskAlignment.BytesPerPhysicalSector << std::endl;
    std::cout << "Logical sector size: " diskAlignment.BytesPerLogicalSector << std::endl;

    return 0;
}

运行上述代码的结果如下:

Physical sector size: 4096
Logical sector size: 512

运行fsutil将产生相同的意外结果。

C:\WINDOWS\system32>fsutil fsinfo ntfsinfo c:
NTFS Version   :                  3.1
LFS Version    :                  2.0
Number Sectors :                  0x000000001741afff
Total Clusters :                  0x0000000002e835ff
Free Clusters  :                  0x0000000000999d28
Total Reserved :                  0x0000000000003260
Bytes Per Sector  :               512
Bytes Per Physical Sector :       4096
Bytes Per Cluster :               4096
Bytes Per FileRecord Segment    : 1024
Clusters Per FileRecord Segment : 0

我做错了什么?

看起来你格式化那个驱动器不正确。如果你错误地匹配逻辑扇区大小和物理扇区大小,将会影响性能。(逻辑扇区大小应该与物理扇区大小相同) - Mgetz
@Mgetz 这是一台运行双系统的MacBook PRO - 是苹果错误地格式化了我的SSD硬盘吗?奇怪的是,我敢肯定几个月前同样的代码能够正确返回512字节。 - user152949
此外:http://blogs.msdn.com/b/ntdebugging/archive/2011/06/28/ntfs-and-4k-disks.aspx?Redirected=true 很难说,这可能会在UEFI固件中得到缓解。有很多因素需要考虑,但如果实际物理扇区大小为4096,则我不会感到惊讶。 - Mgetz
更多相关信息:http://msdn.microsoft.com/zh-cn/library/windows/desktop/hh848035(v=vs.85).aspx - Mgetz
@Mgetz,这些应该是所谓的“高级格式”或512E(4K物理和512字节逻辑扇区大小)磁盘吗? - user152949
我认为这很有可能。 - Mgetz
2个回答

2

这里没有任何问题。来自MSDN的“文件缓冲”文章:

应用程序开发者应该注意市场上推出的新型存储设备,其物理介质扇区大小为4,096字节。这些设备的行业名称为“高级格式”。由于直接将4,096字节引入介质寻址单元可能存在兼容性问题,因此暂时的兼容性解决方案是引入模拟常规512字节扇区存储设备的设备,但通过标准ATA和SCSI命令提供有关真实扇区大小的信息。由于这种仿真,开发人员需要了解两种扇区大小:

  • 逻辑扇区: 用于介质逻辑块寻址的单位。我们也可以认为它是存储可以接受的最小写入单位。这是“仿真”。
  • 物理扇区: 用于完成对设备的读写操作的单个操作的单位。这是原子写入的单位,并且无缓冲I/O需要对齐以获得最佳性能和可靠性特性。

-1
4096字节是8个扇区,被称为簇。当您保存文件时,将其保存到一个或多个簇中。如果文件大小大于512字节,则会保存到一个簇中。空扇区称为松弛区。一些恶意软件将自己写入空闲扇区中,以便藏匿在明处。 FAT文件系统使用16或32个扇区来组成一个簇。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接