跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

C++如何获取硬盘分区的详细挂载点与剩余空间 _ filesystem库实战【实战】

std::filesystem::space返回路径所在文件系统的空间信息,而非挂载点路径;它不解析符号链接、不枚举分区、不提供设备名或挂载点位置,仅封装statvfs/GetDiskFreeSpaceEx,作用域限于路径所属挂载单元。 用
std::filesystem::space
获取分区剩余空间时,为什么总是返回根目录信息? 因为
std::filesystem::space
接收的是路径,但它不自动识别“挂载点”,而是向上遍历直到找到该路径所属的文件系统根(即挂载点)。如果你传入
"./"
或
"/home/user"
,它返回的是
/
或
/home
所在文件系统的空间数据——但你并不知道这个“所在文件系统”具体挂载在哪条路径上。 解决办法是先找出路径对应的挂载点,再调用
space
。C++20 标准库本身不提供挂载点枚举功能,必须依赖系统接口。 Linux 下读取
/proc/mounts
或调用
getmntent()
(需
) macOS / BSD 下用
getfsstat()
(需
) Windows 下用
GetVolumeInformationByHandleW()
+
FindFirstVolumeW()
Linux 下如何用
getmntent
枚举所有挂载点并匹配路径? 核心思路:遍历
/proc/mounts
,对每个挂载点用
std::filesystem::equivalent
判断目标路径是否位于其子树中(注意:不能只靠字符串前缀匹配,比如
/mnt/data
和
/mnt/data2
会误判)。 示例关键逻辑: 立即学习 “ C++免费学习笔记(深入) ”; C知道 CSDN推出的一款AI技术问答工具 下载
FILE* fp = setmntent("/proc/mounts", "r"); struct mntent* ent; while ((ent = getmntent(fp)) != nullptr) { std::filesystem::path mountpoint(ent->mnt_dir); try { if (std::filesystem::equivalent(target_path, mountpoint) || std::filesystem::is_subdirectory(target_path, mountpoint)) { auto space_info = std::filesystem::space(mountpoint); // space_info.capacity, .free, .available } } catch (...) { /* 权限不足或路径不可访问 */ } } endmntent(fp);
务必用
std::filesystem::is_subdirectory
而非
target_path.string().starts_with(...)
/proc/mounts
可能包含 tmpfs、devtmpfs 等虚拟文件系统,按
ent->mnt_type
过滤(如只留
"ext4"
、
"xfs"
、
"btrfs"
) 某些挂载点(如
/proc
、
/sys
)无法调用
space()
,会抛
std::filesystem::filesystem_error
,需捕获
std::filesystem::space
返回的
free
和
available
有什么区别? 这是最容易混淆的点:
free
是磁盘上未分配的字节数;
available
是当前用户(进程有效 UID)**实际可写入**的字节数——它已扣除 root 保留块(ext 系列默认 5%)、配额限制、以及可能的 overcommit 保护。 监控磁盘告警应优先看
available
,否则可能误报(例如 ext4 上普通用户在只剩 5% 空间时就无法写入)
available
≤
free
,差值在 ext4 上通常就是保留块大小:
(capacity * 0.05)
某些文件系统(如 XFS)不设保留块,此时二者相等 跨平台封装时,为什么不要试图用
std::filesystem::canonical
推导挂载点?
std::filesystem::canonical
只解析符号链接和相对路径,不会跨越文件系统边界。例如
/home
是独立挂载的分区,
canonical("/home/user")
仍返回
/home/user
,而非
/home
—— 它不感知挂载拓扑。 真正可靠的跨平台策略是分治: Linux:坚持用
getmntent
+
equivalent
macOS:用
getfsstat(NULL, 0, MNT_NOWAIT)
获取数量,再分配缓冲区重调,遍历
struct statfs
中的
f_mntonname
Windows:用
FindFirstVolumeW
枚举卷 GUID,再对每个卷调用
GetVolumePathNamesForVolumeNameW
获取挂载路径(可能是驱动器号如
C:\
,也可能是挂载点如
D:\Mount\Data
) 别省略权限检查和异常处理——
/proc/mounts
在容器里可能不可读,Windows 某些卷可能无访问权限,这些都会让
space()
失败。真实场景里,一个路径对应多个挂载点(bind mount)、或挂载点嵌套(如
/mnt/disk1
和
/mnt/disk1/sub
)的情况也得考虑优先级,通常取最长匹配路径。

相关文章