Linux下用statvfs获取挂载点剩余空间最可靠,需传挂载点路径(如"/home")而非设备路径,用f_bavail×f_frsize计算用户可用字节数;Windows须用GetDiskFreeSpaceEx并传宽字符驱动器路径(如L"C:")。

Linux 下用 statvfs 获取挂载点剩余空间最可靠
直接调用 statvfs 是 C++(及 C)在 Linux 上获取分区剩余空间的底层标准方式,比解析 /proc/mounts 或调用 df 命令更轻量、更可控,且不依赖 shell 环境。
关键点在于:必须传入**挂载点路径**(如 "/"、"/home"),不是设备路径(如 "/dev/sda1");否则返回的是该设备文件所在分区的信息,而非目标挂载点的实际使用状态。
-
statvfs返回的f_bavail是普通用户可用块数(已扣除 root 保留空间),f_bfree是所有用户总空闲块数,生产环境推荐用f_bavail - 计算剩余字节数需乘以
f_frsize(非f_bsize),因为f_frsize是文件系统实际分配粒度,f_bsize只是 I/O 优化建议值 - 若对某个路径调用失败(
statvfs返回 -1),常见原因是路径不存在、无权限访问,或路径是符号链接且未启用AT_SYMLINK_NOFOLLOW(但statvfs本身不支持 flag,需先realpath解析)
Windows 下用 GetDiskFreeSpaceEx 需注意宽字符与驱动器格式
Windows 没有“挂载点”概念,只有驱动器盘符(如 "C:")和可移动卷(如 USB 设备)。GetDiskFreeSpaceEx 是唯一稳定获取剩余空间的 Win32 API,但必须传入以反斜杠结尾的完整驱动器路径("D:\"),否则可能返回错误或零值。
- 函数参数要求
LPCWSTR,C++ 中需用L"C:\\"或std::wstring,混用char*会崩溃或返回 0 - 对 NTFS 卷返回真实可用空间;对 FAT32 或 exFAT 卷,若启用了“磁盘配额”,
lpFreeBytesAvailable可能小于lpTotalNumberOfFreeBytes - 该函数不识别挂载到目录的卷(即 Windows 的“装入点”,Mount Point),只认盘符——若需支持装入点,得先用
FindFirstVolumeMountPoint+GetVolumePathNamesForVolumeName枚举,再逐个查
跨平台封装时别硬套 std::filesystem::space
std::filesystem::space 看似完美跨平台,但它在不同编译器/标准库实现中行为不一致:libstdc++(GCC)底层调用 statvfs,但 MSVC 的实现早期版本会 fallback 到 GetDiskFreeSpace(不支持大容量,且不返回可用空间,只返回总空闲),直到 VS 2019 16.8+ 才修复为调用 GetDiskFreeSpaceEx。
立即学习“C++免费学习笔记(深入)”;
- 若项目需兼容旧版 MSVC 或 MinGW-w64(部分版本未实现
space),直接调用会导致链接失败或运行时异常 - 即使可用,
std::filesystem::space不提供挂载点列表,你仍需自己枚举(Linux 读/proc/mounts,Windows 用GetLogicalDrives) - 它返回的
available字段在 Windows 上等价于lpFreeBytesAvailable,但 Linux 下是否扣除 root 保留空间取决于statvfs实现,不可假设一致性
获取所有挂载点列表:Linux 解析 /proc/mounts,Windows 查注册表或 WMI
没有标准 C++ 接口能跨平台列出挂载点。Linux 下最简单可靠的方式是读取 /proc/mounts(每行含设备、挂载点、文件系统类型、选项等),跳过伪文件系统(proc、sysfs、debugfs)即可;Windows 必须用系统 API 或 WMI,注册表路径 HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices 只存设备映射,不反映当前挂载状态。
- Linux 示例:用
std::ifstream逐行读/proc/mounts,用std::istringstream分割,第 2 列即挂载点路径,过滤掉nodev或noexec类型(视需求而定) - Windows 更稳妥的做法是用 WMI 查询
Win32_Volume类,其中DriveLetter和Capacity字段明确,且支持装入点(DriveLetter为空时看MountPoint) - 注意:某些容器环境(如 Docker)中
/proc/mounts显示的是宿主机视图,若需容器内真实挂载点,应优先读/proc/self/mountinfo(格式更详细,含挂载 ID 和父挂载 ID)
statvfs 阻塞或失败,或 Windows 网络驱动器断开后 GetDiskFreeSpaceEx 返回 0 而不报错。这类情况必须加超时控制(Linux 可设 alarm 或用 signalfd,Windows 可用 CreateThread + WaitForSingleObject 包裹),不能只靠 errno 或返回值判断。


















