无法直接判断路径是否在nvme盘上,windows需用getvolumeinformationbyhandlew获取卷根句柄并检查bustypenvme(值18),linux需通过/proc/mountinfo和/sys/block/*/device/modalias反查设备类型。

用 GetVolumeInformationByHandleW 检查卷的存储类型(Windows)
直接判断“某个路径是否在NVMe盘上”没有API直答,但Windows从10 2004起支持通过卷句柄获取物理存储总线类型。关键不是看盘符,而是打开路径所在卷的根目录句柄,再调用 GetVolumeInformationByHandleW 获取 FILE_FS_DEVICE_INFORMATION 结构里的 Characteristics 和底层总线类型。
常见错误是传入文件句柄而非卷根目录句柄,或忽略 dwFileAttributes 必须含 FILE_ATTRIBUTE_DIRECTORY 才能成功打开卷根。
- 先用
PathCchCanonicalize或GetFullPathNameW归一化路径,再用PathCchRemoveFileSpec截出卷根(如L"C:\\") - 用
CreateFileW打开卷根,dwDesiredAccess = 0,dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE,dwFlagsAndAttributes = FILE_FLAG_BACKUP_SEMANTICS - 调用
GetVolumeInformationByHandleW,检查返回的lpVolumeDeviceGuid是否非空,并读取lpVolumeDeviceGuid->BusType - NVMe设备的
BusType值为BusTypeNvme(定义在winioctl.h中,值为 18)
Linux下用 ioctl(fd, BLKGETDISKSEQ) + sysfs 路径反查(不推荐)
Linux没有统一接口返回“NVMe与否”,stat() 和 ioctl(BLKSSZGET) 都无法区分SATA SSD和NVMe。可靠做法是:从文件路径反推其所在块设备名(如 sda → nvme0n1),再查 /sys/block/<dev>/device/modalias</dev> 或 /sys/block/<dev>/device/uevent</dev>。
容易踩的坑是路径可能跨挂载点(如bind mount、overlayfs),statfs() 只给挂载点信息,不反映物理设备。必须用 openat(AT_FDCWD, path, O_PATH) + ioctl(..., BLKGETSIZE64) 确认是否块设备,再通过 /proc/self/fd/<fd></fd> 的符号链接解析真实设备路径。
PyCharm 2026.2.0.1 Windows版提供 JetBrains 官方 2026.2.0.1 版本安装包,适合在Windows系统上进行 Python 项目开发、运行、调试和测试。
- 对任意路径,先
stat()得到st_dev,再遍历/proc/self/mountinfo找到对应挂载的major:minor - 从
/proc/self/mountinfo提取该挂载的source字段(如/dev/nvme0n1p1) - 提取设备名(如
nvme0n1),检查/sys/block/<dev>/device/modalias</dev>是否含"nvme" - 注意容器环境里
/sys可能被挂载为只读或隔离,modalias文件可能不存在
为什么不能只靠 GetDriveTypeW 或 statfs() 判断?
GetDriveTypeW 返回 DRIVE_FIXED 对NVMe、SATA SSD、甚至老式机械盘都一样;statfs() 的 f_type 是文件系统类型(如 XFS_SUPER_MAGIC),和物理介质完全无关。有人试过用读写延迟粗略估计——但用户态测得的延迟受I/O调度器、队列深度、缓存影响极大,同一块NVMe在不同负载下测出“像HDD”很常见。
真正区分NVMe的关键特征是:PCIe总线接入、无传统控制器寄存器、支持多队列与Doorbell机制。这些只有内核或驱动层可确认,用户态只能借道系统提供的设备元数据接口。
- Windows上误用
IOCTL_STORAGE_QUERY_PROPERTY查StorageAdapterProperty可能返回StorageIde即使实际是NVMe(因兼容模式) - Linux上
lsblk -d -o NAME,ROTA,TRAN的TRAN列虽显示nvme,但该字段来自sysfs,不可直接用于程序逻辑(无稳定ABI保证) - 跨平台封装库(如libudev)在容器或WSL中常失效,
udevadm info命令本身依赖host udev服务
实际部署时最易被忽略的边界情况
路径指向的是符号链接、挂载点子目录、或ReFS卷上的文件时,卷根推导逻辑会断链。比如 C:datapplog.txt 实际挂载自 \?Volume{...},而该卷映射到了 D:,但 D: 并未在环境变量中配置——此时硬切盘符会误判。
另一个隐形陷阱是Windows Storage Spaces或Linux LVM:物理NVMe盘组成了逻辑卷,上层看到的是 StorageSpace 或 dm-0,其 BusType 或 modalias 显示的是虚拟层类型,不是后端NVMe。
- 务必用
GetVolumePathNameW(Windows)或findmnt -n -o SOURCE(Linux)获取路径真实归属的卷/设备 - 对Storage Spaces,需进一步查
GetStorageDependencyInformation;对LVM,要解析/dev/mapper/xxx底层的dmsetup deps输出 - 没有权限访问
/sys或打开卷句柄时,应降级返回“未知”,而不是抛异常或假阳性
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










