linux 用 (st_dev, st_ino) 唯一标识文件,windows ntfs 用 (卷序列号, fileid),二者不可混用;跨平台须分平台组合字段或改用内容哈希。

Linux 下能直接拿到 st_ino 和 st_dev,Windows 根本没有 inode 概念,所谓“获取 inode 号”在 Windows 上是无效操作——它用的是 USN 日志、文件 ID 或对象 ID,且仅限 NTFS 卷。
Linux:stat() 是唯一靠谱入口,但必须配对 st_dev
调用 stat() 填充 struct stat 后,sb.st_ino 才是你要的 inode 编号,但单独看它毫无意义:
-
stat()返回 -1 时,sb.st_ino是未初始化垃圾值,必须先检查返回值 - 路径若为软链接,默认会跟随;要读链接自身 inode,得换
lstat() -
st_ino只在同一个挂载点内唯一,跨设备(比如/和/home)完全可能重复 - 真正唯一标识一个文件实体的是组合
(sb.st_dev, sb.st_ino),二者缺一不可 - 打印时用
%lu或更安全的PRIu64(需#include <inttypes.h></inttypes.h>)
Windows:没有 inode,只有 FileID / ObjectID / USN
NTFS 卷上可用 GetFileInformationByHandle() 获取 BY_HANDLE_FILE_INFORMATION,其中 nFileIndexHigh 和 nFileIndexLow 拼起来是 64 位 FileID,它在卷内唯一,类似 inode 的语义:
- 该 ID 在卷重格式化后失效,不跨重启持久(除非启用
OBJECT_ID并显式设置) - FAT32/exFAT 卷不支持
FileID,调用返回 0,不能当作有效值使用 -
GetVolumeInformation()可取卷序列号(lpVolumeSerialNumber),但它不是设备 ID,也不参与文件唯一性判定 - 别试图把
FileID当作 Linux 的st_ino直接比较——二者设计目标、生命周期、稳定性完全不同
fstat() 比 stat() 更稳,尤其在文件被删/重命名后
如果你已经用 open() 拿到了文件描述符 fd,优先走 fstat(fd, &sb):
- 它不依赖路径字符串,绕过路径解析、权限检查和符号链接展开,无 TOCTOU 竞态
- 即使文件已被
unlink()删除,只要fd没关,fstat()仍能正确返回原始st_ino和st_dev - 对 pipe、socket 等非文件系统对象调用也会成功,但
st_ino通常为 0,此时不应参与去重逻辑 - 容器或 namespace 环境下,
st_dev值可能被隔离,宿主机看到的和容器内不一定一致
跨平台代码里最易踩的坑
写一个“同时支持 Linux/Windows 获取文件唯一标识”的函数,最容易翻车的地方是:
- 在 Windows 上硬塞
st_ino字段到结构体里,然后传给下游做比较——这字段根本没被赋值,值是栈上随机数 - 把 FAT32 卷上的
FileID == 0当作错误忽略,继续用路径字符串 fallback——路径比对无法识别硬链接 - 用
GetFileInformationByHandle()拿到FileID后,没同步获取卷序列号,导致不同 NTFS 卷上出现 ID 冲突误判 - 在 Linux 上只存
st_ino到数据库,重启后发现同一文件在不同挂载点(如 bind mount)上st_dev不同,查不到记录
真正可靠的跨平台文件唯一性,要么放弃底层标识、改用内容哈希(如 SHA256),要么在各自平台严格按规则组合字段:(st_dev, st_ino) for Linux,(volume_serial, file_id) for NTFS —— 并且永远不混用。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











