必须穿透到物理设备层判断:Windows需管理员权限调用IOCTL_STORAGE_QUERY_PROPERTY查BusType和DeviceMediaType,Linux读/sys/block/*/device/transport与queue/rotational交叉验证,macOS无可靠用户态方案。

不能只看路径名或盘符,必须穿透到物理设备层查总线协议和介质类型;Windows 需管理员权限 + IOCTL 或 WMI,Linux 依赖 /sys/block/ 下的 transport 和 rotational,macOS 几乎无可靠方案。
Windows:用 IOCTL_STORAGE_QUERY_PROPERTY 查 BusType 和 DeviceMediaType
仅靠 GetDriveType 或 GetVolumeInformation 完全无效——它们不区分 SATA SSD 和 NVMe SSD。真正能确认 NVMe 物理分区的,是打开对应 \.PhysicalDriveX 句柄后查询两个关键属性:
- 先从路径(如
"C:\data\file.txt")调用GetVolumePathName得到卷根("C:\"),再用GetVolumeNameForVolumeMountPoint转成"\?\Volume{...}\" - 用该 Volume GUID 打开卷句柄,发送
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,从中提取DiskNumber(不是硬写PhysicalDrive0) - 拼出
"\\.\PhysicalDrive%d",以GENERIC_READ+FILE_SHARE_READ | FILE_SHARE_WRITE打开——这步必须有管理员权限,否则CreateFile返回ERROR_ACCESS_DENIED - 向该句柄发
IOCTL_STORAGE_QUERY_PROPERTY,分别请求StorageAdapterProperty(查BusType == BusTypeNVMe)和StorageDeviceProperty(查DeviceMediaType == DeviceMediaNVMe或DeviceMediaSSD)
注意:BusTypeNVMe 在 Windows 10 1607+ 才定义;若 BusType 是 BusTypeAta 但 DeviceMediaType 是 DeviceMediaSSD,说明是 SATA SSD,不是 NVMe。
Linux:读 /sys/block/*/device/transport 和 /sys/block/*/queue/rotational
Linux 没有“NVMe SSD”单一标识,但可通过两个 sysfs 文件交叉验证:一个确认协议(NVMe),一个确认介质(非旋转)。难点永远在“路径 → 块设备名”的映射是否穿透虚拟层:
立即学习“C++免费学习笔记(深入)”;
- 用
stat()获取路径的st_dev(不是st_rdev),转成主次设备号(major(st_dev),minor(st_dev)) - 拼路径
/sys/dev/block/<maj>:<min>/device/transport</min></maj>,若存在且内容为"nvme",即确认 NVMe 协议 - 同时读
/sys/dev/block/<maj>:<min>/queue/rotational</min></maj>,值为0表示非旋转介质(大概率是 SSD/NVMe);若为1,哪怕设备名含nvme,也可能是模拟盘或驱动异常 - 若
/device/transport不存在(如某些老内核的 NVMe-fabrics 设备),可 fallback 到检查/device/nvme目录是否存在——NVMe 驱动必建此目录
别依赖 /dev/nvme0n1p1 这种名字:LVM、mdraid、btrfs subvolume 可能把它重映射为 /dev/dm-0,此时要顺着 /sys/dev/block/<maj>:<min>/dm/uuid</min></maj> 反查原始设备。
Windows WMI 方案:查 MSFT_PhysicalDisk.MediaType 和 InterfaceType
WMI 不需要管理员权限(但部分类可能受限),适合不想提权的场景,但链路更长、失败点更多:
- 先用
GetVolumePathName把路径归一化为卷根,再通过 WMI 查询Win32_Volume,匹配DeviceID(形如"\\?\Volume{...}") - 用
ASSOCIATORS OF语句关联到MSFT_DiskToVolume→MSFT_PhysicalDisk,避免直接靠盘符硬匹配(跨区卷、存储池会断链) - 检查
MediaType字段:值为3(SSD)、4(NVMe)才可信;InterfaceType字段值为"NVMe"(全大写)进一步佐证协议 - 别查
Win32_DiskDrive.Model或MediaType字符串——OEM 固件常填空或乱写,MediaType在Win32_DiskDrive类里只是描述性字段,不反映真实物理属性
WMI 查询需提前调用 CoInitializeEx 和 CoSetProxyBlanket,否则在服务进程或 COM 上下文受限时静默失败。
为什么 macOS 几乎无法可靠判断
macOS 没有公开、稳定的用户态接口暴露 NVMe 协议或 SSD 介质信息。虽然 IOKit 中 kIOBlockStorageDeviceMediumTypeKey 理论上可返回 kIOBlockStorageDeviceMediumTypeSolidState,但实际只对 Apple 原装 NVMe SSD 可靠;第三方 NVMe 板卡、USB-C 外置 SSD、PCIe 转接盘普遍返回 kIOBlockStorageDeviceMediumTypeGeneric 或空值。即使 diskutil info /dev/disk2 显示 Medium Type: SSD,其来源是 IOKit 的 kIOPropertyMediumTypeKey,同样受固件实现影响,不可用于程序逻辑判断。真要区分,只能退回到性能采样(如随机读延迟


















