c++oding="utf-8" ?>
Linux 下用 statvfs 获取挂载点剩余空间最可靠,Windows 下必须用 GetDiskFreeSpaceEx;跨平台直接调 std::filesystem::space(C++17)虽简洁,但部分旧环境不支持或返回错误值,不能无脑信任。

Linux 下用 statvfs 获取挂载点剩余空间最可靠,Windows 下必须用 GetDiskFreeSpaceEx;跨平台直接调 std::filesystem::space(C++17)虽简洁,但部分旧环境不支持或返回错误值,不能无脑信任。
Linux:用 statvfs 精确读取每个挂载点的块级信息
statvfs 是 POSIX 标准接口,能拿到 f_bsize(文件系统 I/O 块大小)、f_frsize(基本分配单元)、f_blocks(总块数)、f_bfree(空闲块数)、f_bavail(非 root 用户可用块数)等原始数据,比 shell 命令更可控。
常见错误是把 f_bfree 当作用户可用空间——它包含保留块,实际应优先用 f_bavail 计算剩余空间。另外,传入路径必须是**已挂载目录**(如 "/home"),不能是设备节点(如 "/dev/sda1")。
实操建议:
- 遍历
/proc/mounts或调用setmntent("/proc/mounts", "r")获取所有挂载点,过滤掉tmpfs、sysfs等虚拟文件系统 - 对每个挂载点路径调用
statvfs(path, &buf),检查返回值是否为 0,失败时用strerror(errno)排查(常见ENOENT表示路径不存在,ENOTBLK表示非挂载点) - 计算可用字节数:
buf.f_bavail * buf.f_frsize;总容量:buf.f_blocks * buf.f_frsize
Windows:必须用 GetDiskFreeSpaceEx,GetDiskFreeSpace 已过时
GetDiskFreeSpace 返回的是簇(cluster)数量,且不区分“总/可用/可用给管理员”,在 NTFS 上容易误判;GetDiskFreeSpaceEx 直接返回三个 ULARGE_INTEGER* 指针,分别对应总空间、可用空间、用户可用空间(考虑配额),是唯一推荐方式。
关键细节:
- 路径必须以驱动器根目录形式传入,例如
"C:\",末尾反斜杠不能省略,否则函数失败并返回ERROR_INVALID_NAME - 返回的字节数是真实逻辑大小,无需乘法换算;但注意
ULARGE_INTEGER需通过.QuadPart成员访问 64 位值 - 若目标卷被脱机或权限不足,函数返回
FALSE,需用GetLastError()判断(如ERROR_ACCESS_DENIED)
C++17 std::filesystem::space 的坑与适用边界
这个接口写起来最干净:auto s = std::filesystem::space("/home"),返回结构体含 capacity、free、available 字段。但它底层依赖 OS API,在不同平台表现不一:
- Linux 上多数 libc 实现调用
statvfs,但 glibc 2.28 之前对某些网络文件系统(如 NFS)可能返回-1表示未知 - Windows 上 MSVC 2019+ 支持良好,但 MinGW-w64 的 libstdc++ 旧版本会直接返回
static_cast(即全 1)表示错误,且不抛异常(-1) - 路径不存在或不可访问时,标准未强制要求抛
std::filesystem::filesystem_error,有些实现静默返回无效值
所以,除非你明确控制编译环境(如只跑在较新 MSVC 或 glibc ≥ 2.30 的机器上),否则不能跳过错误检查。建议始终包裹 try-catch,并验证 s.capacity != uintmax_t(-1)。
跨平台封装时最容易忽略的两个点
一是挂载点发现逻辑完全不通用:Linux 查 /proc/mounts 或 getmntent,Windows 要用 GetLogicalDrives + GetDriveType 过滤出 DRIVE_FIXED 卷;二是“可用空间”语义差异——Linux 的 f_bavail 默认预留 5% 给 root,Windows 的 available 则受磁盘配额和 USN 日志影响,数值不可直接对比。
如果你要显示“用户还能存多少文件”,务必用各自平台推荐的字段(Linux 用 f_bavail,Windows 用 lpFreeBytesAvailable),而不是统一套用 free 字段。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











