Windows下用GetDriveType判断路径是否为可移动媒体,必须传入根路径(如"F:"),返回DRIVE_REMOVABLE才确认是U盘或SD卡;Linux需通过stat获取设备号,再查/sys/block/sdX/removable值为1判定,跨平台不可统一抽象。

Windows下用GetDriveType判断路径所在驱动器类型
直接调用GetDriveType是最常用且可靠的方式,它不依赖路径是否存在或是否可访问,只看驱动器根目录的设备类型。传入形如"F:\"或"F:"的字符串(注意必须是驱动器根路径),返回值为DRIVE_REMOVABLE即表示可移动媒体。
常见错误是传入文件路径(如"F:\data\file.txt")——函数会自动截取盘符并补上:\,但若路径格式不规范(比如缺反斜杠、含多余空格),可能返回DRIVE_NO_ROOT_DIR或DRIVE_UNKNOWN。
- 务必先用
PathStripToRoot或手动提取盘符+冒号+反斜杠,例如"E:\abc"→"E:\" - 路径需为本地路径;网络映射盘(如
Z:映射到\servershare)返回DRIVE_REMOTE,不是DRIVE_REMOVABLE - U盘、SD卡读卡器、USB硬盘通常返回
DRIVE_REMOVABLE;部分USB硬盘可能返回DRIVE_FIXED(取决于控制器枚举方式)
Linux下通过sysfs识别可移动设备
Linux没有统一API,得靠解析/sys/block/*/removable和/sys/block/*/device/type。给定路径如/media/user/usb-stick,先用stat获取设备号(st_dev),再查对应major:minor在/sys/dev/block/下的软链接目标,最终定位到/sys/block/sdX子目录。
关键点在于:可移动性由硬件报告,内核写入/sys/block/sdX/removable(内容为1或0),而非挂载选项决定。某些USB-SATA桥接设备可能误报为0,需结合/sys/block/sdX/device/type(值为"0"表示磁盘,"13"表示CD-ROM,"14"表示可移动磁盘)交叉验证。
立即学习“C++免费学习笔记(深入)”;
- 不要依赖
mount命令输出里的remov标记——那是用户手动挂载参数,非设备本质属性 -
/proc/mounts里无法区分U盘和内置SSD,必须走sysfs - 权限足够时才可读sysfs;若无权限,
open("/sys/block/.../removable")失败,应视为未知而非不可移动
C++跨平台封装要注意的边界情况
不能简单封装成“is_removable(path)”,因为Windows和Linux对“可移动”的定义粒度不同:Windows以驱动器为单位,Linux以块设备为单位。同一物理设备(如带多个分区的U盘),Windows下整个F:算可移动,Linux下/dev/sdb1和/dev/sdb2共享同一个/sys/block/sdb/removable值,但路径/mnt/usb1和/mnt/usb2需分别查各自设备号。
- 路径必须先
realpath(Linux)或GetFullPathName(Windows)标准化,否则符号链接或相对路径会导致设备号/驱动器提取错误 - Windows下
GetDriveType("A:\")在无软驱时代常返回DRIVE_REMOVABLE但实际不可用,建议额外调用GetVolumeInformation确认卷标存在 - Linux下
stat可能因路径不存在而失败,此时应回退到解析挂载点(/proc/self/mountinfo),而非直接返回false
为什么GetVolumeInformation的dwFlags参数不适用
有人尝试用GetVolumeInformation的dwFlags输出参数中的FILE_REMOTE_DEVICE或FILE_REMOVABLE_MEDIA位来判断,这是错的。FILE_REMOVABLE_MEDIA仅表示该卷使用可移动介质(如软盘、Zip盘),现代U盘/SD卡**几乎从不设置此标志**——它已被弃用多年,微软文档明确说明“此标志对USB闪存驱动器无效”。
真正起作用的是底层驱动器类型,而非卷特性。硬编码检查这个flag只会漏掉所有主流USB存储设备。
- Windows SDK头文件中
FILE_REMOVABLE_MEDIA定义为0x00000001,但U盘调用GetVolumeInformation后该位基本为0 -
FILE_REMOTE_DEVICE对应网络驱动器,与可移动无关 - 唯一正解仍是
GetDriveType+ 驱动器根路径
realpath或GetFullPathName就直接传参,或者Linux下open("/sys/...")失败后直接放弃,都会导致U盘识别率大幅下降。


















