用stat()获取inode编号最稳妥,传入路径即可得st_ino;硬链接需st_ino与st_dev均相等且st_nlink≥2;软链接用lstat()判断,stat()会自动解引用。

用 stat() 获取 inode 编号,别用 fstat() 搞混
直接调 stat() 是最稳妥的方式,传入路径字符串即可拿到 struct stat,其中 st_ino 就是 inode 编号。别一上来就用 fstat()——它需要先 open() 文件,对只读路径或权限受限的文件反而容易失败,还多绕一步。
-
stat()接收const char*路径,不依赖打开状态,适合快速探查 - 注意路径必须是真实存在的,软链接会被自动解引用(即返回目标文件的 inode),这不是 bug,是 POSIX 行为
- 若要获取软链接自身的 inode(即 link 文件本身的 inode),得用
lstat() - 在 ext4/xfs 等常见文件系统上,
st_ino是 64 位整数,用%lu或std::to_string(st.st_ino)输出,别用%d截断
判断硬链接:看 st_nlink 是否大于 1
硬链接的本质是多个目录项指向同一个 inode,所以核心依据不是“名字是否相同”,而是 st_nlink 字段值是否 ≥ 2。这个字段表示该 inode 当前被多少个目录项(即硬链接)引用。
-
st_nlink是内核维护的计数器,只要存在另一个ln oldfile newfile,它的值就加 1 - 普通文件新建后默认为 1;目录默认为 2(
.和父目录中的条目),子目录每增一个,父目录的st_nlink也加 1 - 注意:NFS 或某些虚拟文件系统可能不准确更新
st_nlink,不能完全依赖它做强一致性判断 - 不要试图通过比较两个路径的
st_ino来“发现”硬链接——这只能说明它们指向同一 inode,但无法区分是硬链接还是巧合(比如 bind mount 或 overlayfs 场景)
跨文件系统时 st_dev 必须一致才谈硬链接
同一个 inode 号在不同设备上毫无意义。硬链接的前提是两个路径位于同一挂载点、同一文件系统,因此必须同时满足 st_ino 相等 且 st_dev 相等。
-
st_dev是设备 ID(主+次设备号),可用major(st.st_dev)/minor(st.st_dev)拆解,但通常直接比==就行 - 常见坑:把
/home/user/file和/mnt/backup/file的st_ino一比就下结论,结果一个是 ext4 一个是 btrfs,st_dev差十万八千里 -
df .或stat -c "%d" .可快速确认当前路径所在设备 ID
用 lstat() 区分软链接和硬链接本身
如果目标路径是个软链接,stat() 返回的是它指向的目标文件的信息,而 lstat() 才返回软链接文件自身的元数据——包括它自己的 st_ino 和 st_nlink(通常是 1)。
立即学习“C++免费学习笔记(深入)”;
- 想确认某个路径是不是软链接?看
lstat()得到的st_mode & S_IFLNK是否为真 - 想检查软链接是否“悬空”(目标不存在)?
stat()失败 +lstat()成功 = 典型软链接且已损坏 - 硬链接不可能是“悬空”的——它和原文件共享 inode,删光所有硬链接才会真正释放 inode
stat/lstat、忽略 st_dev、误读 st_nlink 含义,是线上排查时最常卡住的三个点。



















