直接调用statvfs()获取单个挂载点剩余空间最可靠,需传入真实挂载路径(如"/home"),用f_frsize×f_bavail计算非特权用户可用字节数,并检查返回值与errno确保成功。

直接调用 statvfs() 获取单个挂载点剩余空间最可靠
Linux/macOS 下,statvfs() 是获取挂载点空间信息的底层标准接口,比解析 df 或依赖 std::filesystem::space() 更轻量、更可控,也避开了 shell 注入和格式变动风险。它返回的 struct statvfs 包含精确的块级字段,关键是要用对参数和计算方式。
- 必须传入一个**真实存在的路径字符串**(如
"/"、"/home"),不能是空值或非法路径;statvfs()会自动向上查到最近挂载点,不是“路径自身”的空间 - 计算可用字节数时,务必用
buf.f_frsize * buf.f_bavail;别误用f_bsize(那是 I/O 优化块大小,不可用于容量计算) - 返回值为
0表示成功;-1表示失败,需检查errno(常见如ENOENT路径不存在、ENOTDIR中间某段非目录、EACCES权限不足) - 若路径含符号链接,建议先用
realpath()归一化,避免因软链跳转导致查错挂载点
枚举所有挂载点必须解析 /proc/self/mounts,别硬猜路径
标准 C++ 没有跨平台挂载点枚举 API,Linux 下唯一可靠方式是读取内核动态生成的 /proc/self/mounts(比 /proc/mounts 更稳定,不受其他进程修改影响)。手动拼 {"/", "/home", "/boot"} 列表看似简单,但极易遗漏(如 /srv、/mnt/data)或重复(多个路径落在同一分区),且无法获取设备名或文件系统类型。
- 优先用
getmntent()(<mntent.h></mntent.h>)解析,它专为此设计,能正确处理带空格的挂载点路径和逗号分隔的选项字段 - 过滤掉伪文件系统:跳过
fstype为"proc"、"sysfs"、"debugfs"、"tmpfs"、"devtmpfs"的条目,否则statvfs()会失败或返回无意义值 - 挂载点路径需以
/开头、无尾部斜杠(如"/mnt/backup"合法,"/mnt/backup/"可能触发std::filesystem::filesystem_error) - 容器环境(如 Docker)中
/proc/self/mounts可能被裁剪,可 fallback 到/proc/self/mountinfo(格式更复杂,含major:minor设备号)
std::filesystem::space() 不是分区枚举工具,只是封装了 statvfs()
std::filesystem::space() 本质是 POSIX statvfs() 或 Windows GetDiskFreeSpaceEx() 的封装,它只返回**输入路径所在挂载点**的统计值,不提供设备名、不识别挂载关系、也不枚举分区。传 "./data" 和传 "/" 若在同一文件系统,结果完全一致——这不是 bug,是设计使然。
- 它适合单点探测(如检查程序数据目录是否还有足够空间),不适合构建“分区管理器”类功能
- 必须捕获
std::filesystem::filesystem_error异常:路径不存在、无读权限、或挂载点被卸载时都会抛出 -
info.available字段才是当前进程实际可用字节数(已扣除 root 预留空间和配额限制);info.free是所有用户可见空闲量,二者在 Linux 上常有显著差异 - Windows 下传盘符路径(如
"C:\")需注意转义:用"C:/"或"C:\\",单反斜杠"C:"会触发编译错误
跨平台方案必须按 OS 分支,没有银弹
Linux、Windows、macOS 对“挂载点”的抽象完全不同:Linux 有 /proc/mounts 和 statvfs(),Windows 用驱动器字母 + GetDiskFreeSpaceEx(),macOS 则需 getmntinfo()。试图用单一标准库接口覆盖全部场景,只会导致漏挂载点、误判类型或运行时崩溃。
- Linux:用
getmntent("/proc/self/mounts")+statvfs()组合,是最小依赖、最高精度的选择 - Windows:用
GetLogicalDrives()获取位掩码,再循环检测 A–Z 盘符;对 NTFS 卷挂载点(无盘符),需额外调用FindFirstVolumeW()枚举 GUID 卷路径 - macOS:不能读
/proc,必须用getmntinfo()(<sys></sys>),返回的是struct statfs数组,字段命名与statvfs略有差异 - 若项目允许第三方依赖,
libstatgrab或libmount+libblkid可统一接口,但会增加部署复杂度
真正容易被忽略的点在于:挂载点不是静态列表,而是运行时状态。/proc/self/mounts 可能瞬间变化,符号链接可能指向不同设备,bind mount 会让同一物理分区出现多个挂载路径。任何生产级实现都必须把路径归一化、错误容忍、类型过滤当作默认动作,而不是可选优化。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











