563
社区成员
发帖
与我相关
我的任务
分享文件元数据 文件元数据不是文件的内容,而是描述文件的属性,比如:
- 文件大小(`st_size`)
- 文件类型(普通文件、目录、设备文件等)
- 权限(`st_mode`)
- 最后修改时间(`st_mtime`)
- 所属用户/组(`st_uid`/`st_gid`)
- 硬链接数(`st_nlink`)
这些信息都存储在 `struct stat` 结构体中,这是两个函数的核心返回载体。
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) |
| 适用场景 | 未打开文件时查询 | 已打开文件时查询 |
| 原子性 | 可能存在竞态(文件被删 / 改名) | 无竞态(文件已打开) |
你代码中用到的核心字段是 `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()`,且调用后要检查返回值(避免获取元数据失败)。