Linux下用stat()获取inode号最直接:调用stat()填充struct stat,检查返回值为0后读取sb.st_ino;需用绝对路径或有效相对路径,跨文件系统唯一性须结合st_dev判断,符号链接默认解析目标,若需自身inode应改用lstat()。
Linux下用
获取i
node
号最直接
在Linux系统中,
是获取文件inode号的标准方式,无需自己解析目录项或调用底层
。它封装了内核的
系统调用,返回结构体
,其中
字段就是你要的inode号。
注意:必须用绝对路径或相对路径访问**已存在**的文件;对符号链接默认返回目标文件的inode(若需链接自身的inode,改用
)。
成功时返回0,失败返回-1并设置
(如
表示文件不存在)
跨文件系统时,inode号仅在本文件系统内唯一;不同分区的两个文件可能有相同
不要用
替代——它需要先
获得fd,而
本身可能触发重定向或权限检查,引入额外失败路径
里
的类型和平台差异
在glibc头文件中定义为
,实际是
(x86_64上通常是64位),但不能直接用
或
接收——某些嵌入式平台或旧ABI可能用32位。
安全写法是始终用
声明变量,并用
格式化输出(
),避免截断或警告。
立即学习
“
C++免费学习笔记(深入)
”;
C函数速查手册(CHM版)
C函数速查手册(CHM版)
下载
在macOS(XNU)上,
也有效,但语义与Linux一致:同一卷内唯一
Windows不支持inode概念,
返回的
是模拟值(通常为0或伪随机),不可用于唯一性判断
如果程序需跨平台且依赖inode做去重,务必加
保护逻辑
为什么
拿到的
有时是0?
当用
遍历目录时,
里的
字段理论上也存inode号,但它受文件系统实现限制:某些FS(如ext4在特定挂载选项下、XFS、Btrfs)可能不缓存或不暴露该值,此时
返回0。
这不是bug,而是POSIX允许的行为。glibc文档明确说明:
“may be 0 if the filesystem does not support it”。所以不能依赖它做可靠判断。
要确保拿到真实inode,必须对每个
调用
(拼出完整路径后)
批量处理时注意性能:大量
会触发多次磁盘I/O;可考虑
+
减少路径解析开销(需Linux 2.6.39+)
系统调用虽能绕过glibc,但返回结构体仍含
,同样可能为0——没解决根本问题
硬链接场景下
的含义和陷阱
多个硬链接指向同一inode,
对任意一个路径调用都会返回相同的
值。这是正确行为,也是判断是否为同一文件的依据(配合
判断同设备)。
但要注意:
字段只反映当前路径所在目录项的链接计数,不是全局引用数;且删除一个硬链接后,其他路径的
不变,直到所有链接被删且无进程打开该inode。
比较两个路径是否指向同一文件,应同时比对
和
,缺一不可(不同设备可能有相同inode号)
不要用
做持久化ID:文件被
或
到另一文件系统后,inode必然变化
备份工具或去重逻辑中,若仅靠
跳过“重复”文件,可能漏掉跨设备的真正重复内容——此时得靠hash
C++里没魔法,
调用本身很简单,但真正难的是理解inode在不同上下文中的边界:它不是全局唯一ID,不跨设备有效,不随路径迁移,也不保证
一定提供。这些细节一旦忽略,调试时就会卡在“为什么两个明明一样的文件inode却不同”或者“为什么
总是0”这种问题上。
stat()stat()getdents64()sys_stat()struct statst_inolstat()stat()errnoENOENTst_inofstat()open()open()struct statst_inost_inoino_tunsigned longintlong longino_t%luprintf("%lu", sb.st_ino)st_inostat()st_ino#ifdef __linux__readdir()d_inoreaddir()struct direntd_inod_inod_inod_namestat()stat()openat(AT_FDCWD, path, O_NOFOLLOW | O_PATH)fstat()getdents64()d_inost_inostat()st_inost_devst_nlinkst_inost_devst_inost_inorename()mvst_inostat()readdir()d_ino