fstat()是linux下通过文件描述符直接获取inode元数据的唯一正确、零竞态方式;它绕过路径解析,直接读取内核中已打开文件关联的inode信息,返回struct stat结构体,包含st_ino、st_mode等字段。

用 fstat() 直接读取文件描述符对应的 inode 元数据
Linux 下,只要手上有合法的文件描述符(比如 open() 或 dup() 返回的整数),就能绕过路径名,直接拿到内核维护的 inode 信息。fstat() 是唯一正确、零竞态、不依赖路径的底层方式——它不查目录树,不解析符号链接,只读 fd 背后那个已打开的 struct file 对象关联的 inode。
常见错误是先用 fcntl(fd, F_GETPATH)(macOS 扩展)或试图从 /proc/self/fd/ 读链接再调 stat():前者在 Linux 不可用,后者引入路径解析开销和竞态(目标文件可能已被移走或替换)。
-
fstat()第二个参数是struct stat*,填入后可立即访问st_ino、st_mode、st_uid、st_mtime等字段 - 注意:
st_ino是该文件系统内的 inode 号,跨挂载点无意义;st_dev必须一起比对才能唯一标识一个文件 - 若 fd 指向 socket、pipe 或 eventfd,
fstat()仍成功返回,但部分字段(如st_size)为 0 或无定义
#include <sys>
struct stat sb;
if (fstat(fd, &sb) == -1) {
// 处理错误,比如 EBADF(fd 无效)
}
// sb.st_ino 就是你要的 inode 号
</sys>
为什么不用 stat() 或 fstatat()?
因为它们都隐含路径操作:stat() 需要绝对/相对路径字符串,触发 VFS 路径查找,可能被 symlink、mount namespace 或 umount 干扰;fstatat(AT_EMPTY_PATH) 虽支持 fd-only 模式,但要求内核 ≥ 2.6.39 且 glibc ≥ 2.14,兼容性不如 fstat() 稳定。
典型翻车场景:你用 readlink("/proc/self/fd/123") 拿到 /tmp/foo (deleted),再拿这个字符串去 stat() —— 结果一定是 ENOENT,因为文件已 unlink。而 fstat(123, &sb) 照常工作,sb.st_ino 依然有效。
-
fstat()不受当前工作目录影响,不触发权限检查(只要 fd 本身可读) - 对 /dev 下的设备文件,
st_rdev字段才有效,st_ino是伪值(通常为 1) - 某些特殊文件系统(如 procfs、sysfs)返回的
st_ino是内核动态生成的,不对应磁盘真实 inode
获取更底层的 inode 内容(如 i_flags、i_state)需要 kernel module?
用户态标准接口止步于 struct stat —— 它是 VFS 层抽象后的干净视图,不暴露内核 struct inode 的实现细节(比如 i_flags、i_state、i_dentry)。想读这些,必须进内核空间:
- 没有安全、通用的用户态方法;
/proc/kcore或/dev/kmem在现代发行版默认禁用且需 root - 通过 eBPF(如
bpf_probe_read_kernel())可在 tracepoint 中安全访问,但需加载 BPF 程序,不是“直接获取” - 调试场景下可用
crash工具附加到运行中内核,但仅限离线分析
所以,如果你看到文档里说“通过 fd 获取 inode 标志位”,基本是在混淆概念:用户态能拿的只有 fstat() 给的那套标准化字段。
注意 st_ino 在不同文件系统中的行为差异
同一个物理文件,在 ext4 上的 st_ino 和在 XFS 上完全不同;NFS 客户端看到的 st_ino 是服务器映射后的值,重启 NFS server 后可能变化;overlayfs 下,上层和下层文件可能有相同 st_ino(因共享底层 inode)。
- 永远不要用
st_ino做跨机器、跨重启的持久化 ID;要用st_dev + st_ino组合,且仅限单机单次运行期 - 对于硬链接,所有链接共享同一
st_ino和st_dev;软链接则fstat()返回的是目标文件的 inode,不是链接自身的 - tmpfs 中的文件也有真实
st_ino,但内存回收后 inode 号会复用,不可长期缓存
真正难的从来不是怎么调 fstat(),而是搞清你拿到的 st_ino 到底代表什么上下文——它只是内核某次打开动作的快照,不是全局唯一的永恒身份证。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











