当前位置:

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

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

C++17/20的std::filesystem::space函数根据给定路径回溯至其文件系统根目录,返回该分区的空间信息。要获取特定分区的数据,需先确定其确切挂载点。标准库未提供枚举挂载点功能,需调用平台特定API:Linux使用getmntent,macOS使用getfsstat,Windows使用GetVolumeInformationByHandle

在C++开发中,尤其是涉及系统工具或监控应用时,获取磁盘分区的详细挂载点与剩余空间是一个常见需求。C++17/20标准库中的std::filesystem为此提供了space函数,但很多开发者初次使用时都会遇到一个困惑:为什么它返回的总是根目录的信息,而不是我想要的特定分区数据?

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

用 std::filesystem::space 获取分区剩余空间时,为什么总是返回根目录信息?

问题的根源在于对std::filesystem::space作用域的理解偏差。这个函数接收一个路径参数,但它并不负责识别“挂载点”。它的工作机制是:从你给定的路径开始,沿着目录树向上回溯,直到找到该路径所属文件系统的根目录(也就是实际的挂载点),然后返回这个挂载点所在磁盘分区的空间信息。

举个例子,如果你传入“./”或“/home/user”,它返回的其实是/或/home所在那个文件系统的数据。关键在于,你只知道结果属于某个文件系统,却无法直接得知这个文件系统具体挂载在哪个路径上。

所以,正确的解决思路需要分两步走:首先,通过系统接口找出目标路径对应的确切挂载点;然后,再对这个挂载点路径调用space函数。遗憾的是,C++20标准库本身并未提供枚举挂载点的功能,我们必须依赖平台特定的API:

  • 在Linux下,通常读取/proc/mounts文件或调用getmntent()函数(需要包含)。
  • 在macOS或BSD系统上,则使用getfsstat()函数(需要)。
  • Windows平台则需调用GetVolumeInformationByHandleW()配合FindFirstVolumeW()等系列函数。

Linux 下如何用 getmntent 枚举所有挂载点并匹配路径?

核心逻辑很清晰:遍历系统所有的挂载点信息,然后判断你的目标路径是否位于某个挂载点的子树下。这里有个常见的陷阱——不能简单地使用字符串前缀匹配。比如,路径/mnt/data和挂载点/mnt/data2,用前缀判断就会出错。

更可靠的方法是使用std::filesystem::equivalent判断是否就是挂载点本身,或者用自定义的is_subdirectory函数(标准库未直接提供,需自行实现)判断是否为子目录。一段典型的关键逻辑示例如下:

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, .a vailable
        }
    } catch (...) { /* 权限不足或路径不可访问 */ }
}
endmntent(fp);

在实现时,有几点需要特别注意:

  • 务必使用基于文件系统等效性的判断,而非字符串操作。
  • /proc/mounts包含了tmpfs、devtmpfs等虚拟文件系统,通常需要根据ent->mnt_type过滤,只保留如“ext4”、“xfs”、“btrfs”等物理磁盘文件系统。
  • 对于/proc、/sys这类特殊挂载点调用space()可能会抛出std::filesystem::filesystem_error异常,务必做好捕获和处理。

std::filesystem::space 返回的 free 和 a vailable 有什么区别?

这是另一个容易混淆的概念。简单来说:

  • free:指的是磁盘上物理未分配的、空闲的总字节数。
  • a vailable:指的是当前用户(或进程的有效UID)实际可写入的字节数。

两者的区别在于,a vailable从free中扣除了许多“不可用”的部分,例如ext系列文件系统为root保留的默认5%空间、用户配额限制、以及可能的overcommit保护预留空间。

这意味着,在做磁盘空间监控告警时,应该优先参考a vailable的值。如果只看free,可能会产生误判——例如在一个ext4分区上,当free空间还剩总容量的5%时,普通用户可能就已经无法写入任何文件了,因为那5%是保留给root的。a vailable总是小于或等于free,在ext4上,其差值大致就是那5%的保留块。当然,像XFS这样的文件系统默认不设保留块,两者数值就会相等。

跨平台封装时,为什么不要试图用 std::filesystem::canonical 推导挂载点?

有些开发者会想,既然std::filesystem::canonical可以解析符号链接得到绝对路径,是否可以用来辅助定位挂载点?答案是:不行。

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:\,也可能是NTFS挂载点如D:\Mount\Data)。

最后,别忘了现实世界的复杂性。权限检查和异常处理绝不能省略——在容器环境中,/proc/mounts可能不可读;在Windows上,某些卷可能没有访问权限,这些都会导致space()调用失败。此外,还要考虑一个路径可能对应多个绑定挂载(bind mount),或者存在嵌套挂载点(如/mnt/disk1和/mnt/disk1/sub)的情况。在处理这类场景时,通常的规则是选择最长匹配的那个挂载点路径。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
作者最新文章
编程开发 硬盘 C++
相关文章 更多
C++动态数组初始化怎么写?常用语句与代码示例
C++动态数组初始化怎么写?常用语句与代码示例

深入解析C++中动态数组的初始化机制,涵盖new操作符的不同用法、基本类型与类对象的初始化差异,以及为何在现代C++开发中应优先使用std::vector。

WMV转MP4方法
WMV转MP4方法

WMV视频压缩指南:如何高效“瘦身”释放硬盘空间 在日常处理和收藏视频时,不少人会发现一个有趣的现象:WMV格式的文件,在画质相当的情况下,体积往往比MP4更小巧。这原本是它的优势,但架不住日积月累,一堆WMV文件同样会悄悄吃掉大量的硬盘空间。因此,如何给WMV视频“减减肥”,就成了优化存储、提升效

C++类构造与析构函数详解
C++类构造与析构函数详解

C++类构造与析构函数详解 C++这门语言,可以说是从C语言这棵大树上衍生出的高级果实,如今的应用普及度有目共睹。作为一种静态类型的通用编程语言,它厉害的地方在于融合了多种编程哲学——无论是传统的面向过程,还是主流的面向对象,乃至数据抽象、泛型编程这些高级概念,它都能很好地支持。正因为这份卓越的扩展

C++中std::upper
C++中std::upper

C++中std::upper_bound用法解析 在C++标准模板库(STL)的算法工具箱里,upper_bound() 绝对算得上是一把精准的“探针”。它的核心任务很明确:在一个已经排好序的区间 [first, last) 内,帮你快速定位到第一个**严格大于**指定值 value 的那个元素。这

C++常对象与成员解析
C++常对象与成员解析

C++中“常”概念全景解析:从对象、成员到指针与引用 在C++的世界里,“常量性”是一个强大的保障机制。它不仅仅是一个const关键字那么简单,而是构建健壮、安全程序的重要基石。今天,我们就来系统梳理一下围绕“常”的一系列概念:常成员、常对象、常指针与常引用。理解它们,是写出高质量C++代码的关键一

50TB硬盘来了!希捷2028年正式出货
50TB硬盘来了!希捷2028年正式出货

快科技7月30日消息,希捷CEO戴夫·莫斯利在2026财年第四季度财报电话会上宣布,公司旗下50TB级HAMR(热辅助磁记录)硬盘平台Mozaic 5,将于2027年底启动客户认证,2028年正式出货。这个时间节点很关键,意味着超大容量硬盘的商用化终于进入了倒计时。 莫斯利透露,基于现有长期供应协议

c++如何将结构体写入SQLite数据库_对象关系映射方案【进阶】
c++如何将结构体写入SQLite数据库_对象关系映射方案【进阶】

直接用SQLiteCAPI绑定结构体需要手动处理字段展平与顺序对齐,ORM库虽省代码但存在隐式行为风险。小项目建议原生绑定,中大型项目可搭配编译期校验使用轻量ORM。绑定std::string需传指针与长度,注意生命周期;浮点字段比较需设误差范围。

什么是编程,学习编程的意义是?
什么是编程,学习编程的意义是?

编程是编写程序指令,让设备按意图运行,常用Python、C等语言或Scratch图形化编程。学习编程能跟上科技时代,锻炼自学与解决问题能力,提升逻辑思维,代表行动力,推动事物前进。各司其职,编程者尽本分。

编程是门艺术_是编程艺术吗?
编程是门艺术_是编程艺术吗?

编程被争论是否为艺术。从定义看,编程是技能表达,但并非所有编程都是应用开发。写代码如音乐、文章,有独特风格。好代码需耐心与逻辑能力。编程是艺术,但应用开发不等同于编程艺术。

【编程的感受】
【编程的感受】

很多人提起编程,总觉得这是一门“不起眼”的学问——不就是写写代码嘛,能有多深?但真走进去了才会发现,编程里头的门道,远比表面看上去要丰富得多。 学习编程的过程中,最容易卡住的往往是那些基础语法。就拿那个常见的 for 循环来说吧,刚开始时怎么都绕不过弯来:为什么这么写能循环?循环条件到底怎么控制?一

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

PDF教程
PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
Postman macOS版
Postman macOS版
Mac

Postman是一套面向API全生命周期的开发与测试平台,可在Mac上发送和调试多种协议请求,管理集合、环境及认证信息,并完成脚本测试、模拟服务、监控、文档发布和团队协作。它适合开发、测试及运维人员使用,提供个人免费方案。

Docker Desktop macOS版
Docker Desktop macOS版
Mac

Docker Desktop 是 Docker 官方为 Mac 提供的容器开发环境,集成 Docker Engine、命令行工具、Compose、Build、Kubernetes 与图形化管理界面。

Android Studio macOS版
Android Studio macOS版
Mac

Android Studio 是 Google 面向安卓应用开发提供的官方集成开发环境,基于 IntelliJ IDEA 构建。它整合智能代码编辑、Gradle 构建、界面预览、设备模拟、性能分析、调试测试及 APK 分析等工具。

WINDOWS 更多
Postman Windows版
Postman Windows版
Windows

Postman 是面向 API 全生命周期的开发与协作平台。Windows 桌面版可用于构建和发送 HTTP、GraphQL、gRPC、WebSocket、MQTT 等请求,并提供环境变量、集合、脚本测试、模拟服务、监控、文档及团队工作区等

Docker Desktop Windows版
Docker Desktop Windows版
Windows

Docker Desktop 为 Windows 开发者提供集成式容器环境,内置 Docker Engine、命令行工具、Compose、Build 与 Kubernetes 等组件,可在本机完成镜像构建、容器运行、日志查看和资源管理。

Android Studio Windows版
Android Studio Windows版
Windows

Android Studio 是 Google 面向 Android 应用开发提供的官方集成开发环境,以 IntelliJ IDEA 为基础,集成智能代码编辑、Gradle 构建、设备模拟、界面预览、调试测试及性能分析工具,