linux/macos下用stat()或fstat()获取inode号,需检查返回值、读取st_ino字段并配合st_dev唯一标识;windows无等价概念,st_ino恒为0不可靠。

Linux/macOS 下可以用 stat() 或 fstat() 直接拿到 inode 号;Windows 没有等价概念,强行查会返回 0 或报错。
用 stat() 获取文件 inode 号(POSIX 标准方式)
这是最直接、最便携的方法,适用于已知路径的文件。核心是读取 struct stat 中的 st_ino 字段。
-
stat()接收文件路径字符串,不依赖打开句柄,适合只读元信息场景 - 注意:路径必须存在且进程有执行权限(对目录)、读权限(对文件),否则
stat()返回 -1,errno设为ENOENT、EACCES等 - 不同文件系统对
st_ino的位宽支持不同(如 ext4 是 64 位,某些旧文件系统是 32 位),建议统一用ino_t类型接收,而非硬写uint64_t - 示例关键代码:
struct stat sb;
if (stat("/path/to/file", &sb) == 0) {
printf("inode = %lu\n", (unsigned long)sb.st_ino);
} else {
perror("stat");
}
用 fstat() 获取已打开文件的 inode(避免重复路径解析)
当你已经用 open() 或 fopen() 打开了文件,又需要它的 inode,优先用 fstat()——它跳过路径查找和权限检查,更快更安全。
-
fstat()参数是 fd(int 类型),不是路径;对FILE*需先用fileno()转换 - 即使原文件已被删除(但 fd 仍有效),
fstat()仍能返回原始 inode 号——这是判断“已删但未释放”文件的关键依据 - 注意:如果 fd 来自
/proc/self/fd/这类伪文件,st_ino可能无意义(例如返回 0 或 1)
Windows 下为什么不能可靠获取 inode?
NTFS 有类似概念叫 File ID(由 FILE_INTERNAL_INFORMATION 返回),但它不满足 POSIX inode 的语义:不跨重命名/硬链接保持稳定,且无法通过标准 C++ API 暴露。
- MinGW/MSVC 的
_stat()实现中,st_ino恒为 0(或填充随机值),不可用于逻辑判断 - 试图用
GetFileInformationByHandle()读dwVolumeSerialNumber+nFileIndexLow/High组合模拟 inode,但该组合在卷快照、脱机重定向等场景下可能复用,不唯一 - 跨平台代码若依赖 inode 做去重或变更检测,必须加
#ifdef __linux__ || __APPLE__守卫,Windows 分支应降级为 mtime+size 组合校验
常见误用与陷阱
很多开发者把 inode 当作“文件唯一 ID”,但在实际系统中它只是文件系统层的局部标识,离开上下文就失效。
- 同一 inode 在不同挂载点(bind mount)下呈现相同号,但
stat()返回的st_dev不同——比对文件是否相同,必须同时检查st_dev和st_ino - 容器或 chroot 环境中,
st_dev可能被虚拟化,导致宿主机和容器内看到的st_dev不一致,仅靠st_ino会误判 - tmpfs、devtmpfs 等内存文件系统,inode 号重启即失效,不能持久化存储
- 不要用 inode 做哈希键存入数据库——没有全局唯一性保障,也没有生命周期承诺
真正要靠 inode 做事时,永远带上 st_dev,并确认你的文件系统和运行环境没做任何抽象层拦截(比如 overlayfs、FUSE 实现不完整时 st_ino 可能被重映射)。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











