stat() 和 fstat()

rest1024 2026-05-07 13:25:22

一、核心概念:

文件元数据 文件元数据不是文件的内容,而是描述文件的属性,比如:

- 文件大小(`st_size`)

- 文件类型(普通文件、目录、设备文件等)

- 权限(`st_mode`)

- 最后修改时间(`st_mtime`)

- 所属用户/组(`st_uid`/`st_gid`)

- 硬链接数(`st_nlink`)

这些信息都存储在 `struct stat` 结构体中,这是两个函数的核心返回载体。

二、`stat()` vs `fstat()` 基本用法

1. 函数原型

 #include <sys/stat.h>

// 通过「文件路径」获取文件元数据

int stat(const char *pathname, struct stat *statbuf);

// 通过「文件描述符」获取文件元数据

int fstat(int fd, struct stat *statbuf); 

2. 返回值

- 成功:返回 `0`;

- 失败:返回 `-1`,并设置 `errno`(可通过 `perror()` 打印错误)。

3. 核心区别

特性stat()fstat()
入参文件路径(字符串)文件描述符(int)
适用场景未打开文件时查询已打开文件时查询
原子性可能存在竞态(文件被删 / 改名)无竞态(文件已打开)

三、核心结构体 `struct stat`

你代码中用到的核心字段是 `st_size`(文件大小),先看简化版结构体(不同系统略有差异):

 struct stat {

         off_t st_size; // 文件大小(字节),普通文件有效

         mode_t st_mode; // 文件类型 + 权限

         uid_t st_uid; // 文件所属用户ID

        gid_t st_gid; // 文件所属组ID

         time_t st_mtime; // 最后修改时间

        dev_t st_dev; // 存储设备ID

        ino_t st_ino; // inode号 //

        其他字段... }; 

四、你的代码中的实际应用

以 `load_aof_file` 中的这段代码为例:

 struct stat st;

if (fstat(fd, &st) < 0 || st.st_size == 0) {

        close(fd);

        printf("[Persist] File %s is empty\n", filename);

        return; }

// 后续用 st.st_size 获取文件大小,用于mmap映射

char *mapped_data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 

这段代码的逻辑:

1. 先通过 `open()` 打开文件,得到文件描述符 `fd`;

2. 调用 `fstat(fd, &st)`:将 `fd` 对应的文件元数据写入 `st` 结构体;

3. 检查 `st.st_size == 0`:判断文件是否为空(空文件无需映射);

4. 用 `st.st_size` 作为 `mmap` 的第二个参数:指定映射的内存大小(必须等于文件大小,否则映射会出问题)。

 

五、简单示例:验证两个函数的用法

 #include <stdio.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

int main() {

        // 1. 用 stat() 获取文件元数据(通过路径)

        struct stat st1;

        if (stat("test.txt", &st1) == 0) {

                printf("stat() 获取文件大小:%ld 字节\n", st1.st_size);

         }

        // 2. 用 fstat() 获取文件元数据(通过文件描述符)

         int fd = open("test.txt", O_RDONLY);

        if (fd >= 0) {

                struct stat st2;

                if (fstat(fd, &st2) == 0) {

                        printf("fstat() 获取文件大小:%ld 字节\n", st2.st_size);

                }

                close(fd);

        }

        return 0;

}

输出示例(假设 test.txt 大小为 100 字节):

stat() 获取文件大小:100 字节

fstat() 获取文件大小:100 字节 

总结

1. **核心作用**:`stat()`/`fstat()` 都是获取文件元数据,核心区别是入参(路径 vs 文件描述符); 2. **你的代码场景**:用 `fstat(fd, &st)` 获取已打开文件的大小(`st.st_size`),为 `mmap` 提供映射长度,且避免竞态风险;

3. **最佳实践**:已打开文件优先用 `fstat()`,未打开文件用 `stat()`,且调用后要检查返回值(避免获取元数据失败)。

参考链接:https://github.com/0voice

...全文
117 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

563

社区成员

发帖
与我相关
我的任务
社区描述
零声学院,目前拥有上千名C/C++开发者,我们致力将我们的学员组织起来,打造一个开发者学习交流技术的社区圈子。
nginx中间件后端 企业社区
社区管理员
  • Linux技术狂
  • Yttsam
  • 零声教育-晚晚
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

请新加入的VIP学员,先将自己参加活动的【所有文章】,同步至社区:

【内容管理】-【同步至社区-【零声开发者社区】

试试用AI创作助手写篇文章吧