商城首页欢迎来到中国正版软件门户

您的位置:首页 >c++如何读取Linux系统的/proc/mounts获取磁盘挂载点【实战】

c++如何读取Linux系统的/proc/mounts获取磁盘挂载点【实战】

  发布于2026-05-03 阅读(0)

扫一扫,手机访问

直接读取 /proc/mounts 文件即可,无需系统调用或库函数封装

在Linux系统里,想查看当前有哪些磁盘挂上了,去哪儿找最直接?答案就是 /proc/mounts 这个文件。它本质上是一个由内核动态生成的文本快照,格式固定,内容一目了然。用C++的标准文件流去读它,其实比调用那些封装好的库函数更轻巧、也更可控,还能顺便绕开对 的依赖以及随之而来的内存管理细节。

新手常犯的一个错误是,自己动手解析时,总担心字段里会不会有空格。其实大可不必过度紧张。没错,第4列的挂载选项(比如 relatime,strictatime)确实可能包含逗号,但它本身不会包含空格。而第3列的文件系统类型,以及最后的第5、6列,都永远是单个词。所以,放心地用空格去切分前4个字段,这个操作是安全的。

c++如何读取Linux系统的/proc/mounts获取磁盘挂载点【实战】

用 std::getline + std::istringstream 解析比手写 strtok 更可靠

为什么推荐标准库的这套组合拳?因为 /proc/mounts 每行的字段之间,是用多个连续空格分隔的,而不是制表符。更关键的是,第4列内部用逗号分隔。如果自己写循环去切分,很容易掉进坑里。而标准流里的 >> 提取操作符有个天然优势:它会自动跳过所有多余的空白字符,正好完美适配这种格式。

来看一个核心代码片段:

std::ifstream mounts("/proc/mounts");
std::string line;
while (std::getline(mounts, line)) {
    if (line.empty() || line[0] == '#') continue;
    std::istringstream iss(line);
    std::string dev, mp, fstype, opts;
    if (iss >> dev >> mp >> fstype >> opts) {
        // 此时 mp 就是挂载点路径,如 "/home" 或 "/"
        std::cout << "Mount point: " << mp << "\n";
    }
}

这里有几个细节值得展开说说:

  • 别用 strtok:它会破坏原始字符串,而且对处理多个连续空格的情况并不鲁棒。
  • 不推荐正则:对于这种小文件解析,杀鸡焉用牛刀。况且,C++11的 在某些旧版本的glibc上性能可能不尽如人意。
  • 后续处理:如果你需要进一步分析 opts 字段,比如检查里面是否包含 noexec 选项,再用一个 std::stringstream 按逗号分割一次就行了。

注意权限与挂载命名空间隔离问题

/proc/mounts 本身不需要特殊权限,普通用户就能看。但这里有个至关重要的概念:你看到的内容,取决于你的进程站在哪个“观察点”上,也就是所谓的 mount namespace。

这意味着什么呢?如果你在Docker容器里运行这段代码,默认情况下,你只能看到容器自己这个小世界里的挂载点(比如 /proc, /dev/pts),而看不到宿主机上挂载的 /home/data 目录。这是Linux容器实现隔离的基础机制之一。

  • 想要看到宿主机的全局视图?那你得在特权(privileged)容器里运行,或者通过特殊方式挂载宿主机的 /proc 文件系统(不过一般不建议这么做)。
  • 至于挂载新设备,那当然需要root权限。但仅仅读取现有的挂载信息,是畅通无阻的。

对比 getmntent():何时该换用 C 标准库接口

那么,什么时候才需要考虑使用 getmntent() 这类C库函数呢?主要是在你需要更明确的语义,或者要获取更底层字段的时候。比如,你想过滤出所有 ext4nfs 类型的文件系统,或者需要用到 mnt_freqmnt_passno 这些字段,那么 getmntent() 提供的结构体会更清晰。

不过,使用它也得留神:返回的结构体里字段是裸指针,要注意生命周期管理。而且,在musl libc这样的环境下,其行为可能和glibc略有差异。

  • 配套使用:调用 getmntent() 必须记得配对使用 setmntent()endmntent(),否则可能会有文件句柄泄漏的风险。
  • 路径无关性:一个好处是,getmntent("/proc/mounts", "r") 可以直接读,你不需要在代码里硬编码这个路径字符串。
  • 纯C++项目:如果你的项目想保持纯粹的C++风格,避免C风格的API,那么坚持使用 std::ifstream 的方案完全没问题。两者在性能上几乎没有实质差别,只是代码风格的选择而已。

最后,分享一个实战中极易被忽略的排查思路:当你发现读取的挂载信息不符合预期时,别一头扎进解析逻辑里死磕。先跳出代码,确认一下当前进程所处的挂载命名空间。在systemd service、Podman容器或者chroot环境里,结果很可能天差地别。一个简单的命令 ls /proc/self/ns/mnt,就能帮你快速确认自己的“视角”是否和宿主机一致。很多时候,问题就出在这个上下文上。

本文转载于:https://www.php.cn/faq/2311590.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注