直接调用 stat() 填充 struct stat,st_ino 字段即 inode 编号,st_dev 字段即设备 id(主次设备号合成);必须检查 stat() 返回值是否为 0,否则字段未定义,且 st_ino 仅在同文件系统内唯一。

Linux 下 C++ 获取文件 inode 和设备 ID,直接用 stat() 就行,别碰 lstat() 或 fstat() 除非你明确需要符号链接或已打开的 fd。
怎么用 stat() 拿到 inode 和设备 ID
核心就是调用系统函数填一个 struct stat,里面两个字段直接可用:st_ino 是 inode 编号,st_dev 是设备 ID(主+次设备号合成的 dev_t)。注意不是文件系统 UUID,也不是挂载点路径。
常见错误现象:st_ino 看起来是 0 或极小值 —— 很可能是路径写错、权限不足导致 stat() 失败但没检查返回值;或者传了相对路径但当前工作目录变了。
- 必须检查
stat()返回值是否为 0,否则st_ino/st_dev未定义 - 路径要用绝对路径或确保相对路径上下文稳定(比如用
getcwd()拼接) -
st_dev是设备标识,相同值意味着同一块物理/虚拟设备(如 /dev/sda1),但不同文件系统可能共享同一st_dev(比如 bind mount)
#include <sys>
struct stat sb;
if (stat("/path/to/file", &sb) == 0) {
printf("inode: %lu, device: %lu\n", (unsigned long)sb.st_ino, (unsigned long)sb.st_dev);
}
</sys>
st_dev 和 st_rdev 别搞混
st_dev 是文件所在设备的 ID,所有普通文件、目录都靠它定位存储设备;st_rdev 只对字符/块设备文件有意义,表示该设备文件“指向”的底层设备号(比如 /dev/sda 的 st_rdev 就是 sda 自己的主次号)。
使用场景:判断两个路径是否在同一个挂载点?比 st_dev 更可靠的是结合 statfs() 查 f_fsid,但日常做硬链接检测、去重、缓存隔离,st_dev + st_ino 组合已经足够唯一。
- 对普通文件调
stat()后,st_rdev值无意义,别读它 - 用
mknod创建的设备文件,st_dev是它所在磁盘分区的设备号,st_rdev才是它模拟的硬件设备号 - 容器环境里
st_dev可能被 namespace 隔离,宿主机看到的值和容器内不一定一致
为什么不用 lstat() 或 fstat()
lstat() 会绕过符号链接本身,读取目标文件的 st_ino —— 如果你真想获取符号链接自己的 inode(即链接文件自身的元数据),就得用 lstat();但多数人要的是目标文件的 inode,这时 stat() 更直觉。
fstat() 需要先 open(),多一次系统调用,还带出 fd 管理负担。除非你 already have the fd(比如从 accept() 或 pipe() 来的),否则纯查元数据没必要走这条路。
- 符号链接场景下,
stat()返回目标文件的st_ino,lstat()返回链接文件自身的st_ino -
fstat()的st_ino和stat()对同一文件结果一致,但无法获取路径名相关的信息(比如无法知道这个 fd 是从哪个路径 open 的) - 某些 NFS 或 FUSE 文件系统里,
fstat()可能比stat()少一次网络往返,但这是例外,不是默认行为
真正容易被忽略的是:inode 编号只在单个文件系统内唯一,跨设备比较 st_ino 没意义;而 st_dev 虽然能区分设备,但在 overlayfs、bind mount、user namespaces 下可能失真 —— 如果你在做分布式缓存或一致性校验,别只依赖这两个字段,加一层逻辑路径哈希或内容摘要更稳妥。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











