最可靠的方式是通过 realpath() 归一化路径后,用 getmntent() 逐行比对 /proc/mounts 中的 mnt_dir 字段是否精确匹配;statfs() 无法判断挂载点,仅反映文件系统信息。

Linux下用 statfs() 检查挂载点根路径
直接判断一个路径是否为已挂载文件系统的根节点,最可靠的方式是确认它是否为某个挂载的“挂载点”(mount point),且该路径本身在挂载表中被记录为某次挂载的 target。Linux 提供了 statfs() 和 statvfs(),但它们只能获取文件系统信息,无法直接告诉你“这个路径是不是挂载点”。真正有效的做法是比对路径与系统挂载表(/proc/mounts 或 getmntent())中的 target 字段。
关键点在于:挂载点必须满足两个条件——它存在、且是某个挂载项的完整目标路径(不是子目录)。例如 /home 是挂载点,但 /home/user 不是,即使它们在同一设备上。
-
statfs("/path", &buf)返回成功 ≠ /path 是挂载点;它只说明路径可访问且属于某个文件系统 - 必须读取
/proc/mounts(或调用setmntent("/proc/mounts", "r")),逐行解析target字段,并做精确字符串匹配(注意去除尾部斜杠) - 匹配前需先
realpath("/path", ...)归一化路径,避免/mnt//、/mnt/.等干扰
用 findmnt 命令辅助验证(开发调试时推荐)
实际写 C++ 代码前,建议先用 shell 工具快速验证逻辑是否正确:findmnt 能直接回答“这个路径是不是挂载点”,且输出结构清晰。
例如:
findmnt -T /boot
若输出一行挂载信息,说明是挂载点;若提示 findmnt: No such file or directory 或静默无输出,则不是。
-
findmnt -T /path是最接近语义的命令,它会向上查找最近的挂载点并判断/path是否恰好就是那个点 - 注意
-T参数要求内核支持(2.6.26+),且依赖libmount,但几乎所有现代发行版都满足 - 在 C++ 中不建议
system("findmnt ..."),仅用于快速验证预期行为和边界 case(如 bind mount、overlayfs)
C++ 实现要点:路径归一化 + getmntent() 精确匹配
标准库没有跨平台挂载点检测 API,Linux 下应优先使用 <mntent.h></mntent.h> 接口,而非手动解析 /proc/mounts 字符串(易出错)。
- 调用
realpath("/input/path", resolved)获取绝对规范路径,否则/mnt和/mnt/会被视为不同字符串 - 用
setmntent("/proc/mounts", "r")打开挂载表,循环调用getmntent() - 对每个
struct mntent*的mnt_dir字段,同样调用realpath()(或至少用strcmp()做严格相等比较,前提是确保输入路径已归一化) - 遇到第一个完全匹配的
mnt_dir就可返回true;遍历完无匹配则为false - 别忽略
NULL返回值和endmntent()清理
常见误判场景和坑
很多实现会错误地认为“父目录不是挂载点,当前目录 statfs() dev ID 不同”就说明它是挂载点——这是错的。bind mount、overlayfs、namespace 隔离都会打破这种推论。
- bind mount(如
mount --bind /old /new)会让/new成为独立挂载点,但statfs()的f_fsid可能和原路径相同 - 容器环境中,
/proc/mounts是 host namespace 的视图,而进程可能运行在 mount namespace 中,此时需读/proc/self/mounts - 某些 FUSE 文件系统(如 sshfs)挂载后可能不在
/proc/mounts中,而是在/proc/self/mountinfo,但这种情况极少作为“根节点”使用,通常可不处理 - 不要用
stat()比较st_dev:同一设备上的多个挂载点(如 ext4 分区挂载两次)st_dev相同,但它们互为独立挂载点
归一化路径和精确匹配 /proc/mounts 中的 target 是目前最稳的方案,其他都是妥协或有漏判风险。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











