fstatfs 函数详解
- 函数介绍
fstatfs 是 Linux 系统中用于获取文件系统统计信息的系统调用。可以把这个函数想象成一个”文件系统体检工具”——当你给它一个已打开的文件描述符时,它会告诉你这个文件所在文件系统的详细信息,比如总空间多大、已用多少、还剩多少、支持什么特性等等。
data-ad-format="fluid"
data-ad-layout-key="-7k+ex-4a-9w+4a">
就像你去体检时医生会检查你的身高、体重、血压等指标一样,fstatfs 会检查文件系统的”健康状况”和”基本信息”。
- 函数原型
1 2 3 4
| #include <sys/vfs.h> /* 或者 #include <sys/statfs.h> */
int fstatfs(int fd, struct statfs *buf);
|
- 功能
fstatfs 函数用于获取与指定文件描述符相关的文件系统的统计信息。它填充一个 statfs 结构体,其中包含了文件系统的各种参数和状态信息。
- 参数
- 返回值
常见错误码:
EBADF: fd 不是有效的文件描述符
EFAULT: buf 指针无效
EIO: I/O 错误
ENOSYS: 系统不支持此操作
- 相似函数或关联函数
statfs: 通过文件路径获取文件系统信息(需要文件路径而非文件描述符)
statvfs: POSIX 标准的文件系统信息获取函数(提供更标准化的接口)
fstatvfs: 通过文件描述符获取 POSIX 标准的文件系统信息
stat: 获取文件本身的详细信息(不是文件系统信息)
- struct statfs 结构体详解
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| struct statfs { long f_type; /* 文件系统类型 */ long f_bsize; /* 文件系统块大小 */ long f_blocks; /* 总块数 */ long f_bfree; /* 空闲块数 */ long f_bavail; /* 对非超级用户可用的块数 */ long f_files; /* 总 inode 数 */ long f_ffree; /* 空闲 inode 数 */ fsid_t f_fsid; /* 文件系统 ID */ long f_namelen; /* 最大文件名长度 */ long f_frsize; /* 片段大小 */ long f_spare[5]; /* 保留字段 */ };
|
- 示例代码
示例1:基础用法 - 查看文件系统空间信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/vfs.h>
int main() { int fd; struct statfs fs_info; const char *filename = "/etc/passwd"; // 使用系统文件作为示例 // 打开文件 fd = open(filename, O_RDONLY); if (fd == -1) { perror("open"); return 1; } // 获取文件系统信息 if (fstatfs(fd, &fs_info) == -1) { perror("fstatfs"); close(fd); return 1; } // 显示文件系统信息 printf("=== 文件系统信息 ===\n"); printf("文件: %s\n", filename); printf("文件系统类型: 0x%lx\n", fs_info.f_type); printf("块大小: %ld 字节\n", fs_info.f_bsize); printf("总块数: %ld\n", fs_info.f_blocks); printf("空闲块数: %ld\n", fs_info.f_bfree); printf("可用块数: %ld\n", fs_info.f_bavail); printf("总 inode 数: %ld\n", fs_info.f_files); printf("空闲 inode 数: %ld\n", fs_info.f_ffree); // 计算空间使用情况(以 GB 为单位) double total_space = (double)(fs_info.f_blocks * fs_info.f_bsize) / (1024 * 1024 * 1024); double free_space = (double)(fs_info.f_bfree * fs_info.f_bsize) / (1024 * 1024 * 1024); double avail_space = (double)(fs_info.f_bavail * fs_info.f_bsize) / (1024 * 1024 * 1024); printf("\n=== 空间使用情况 ===\n"); printf("总空间: %.2f GB\n", total_space); printf("空闲空间: %.2f GB\n", free_space); printf("可用空间: %.2f GB\n", avail_space); printf("使用率: %.2f%%\n", (total_space - free_space) / total_space * 100); close(fd); return 0; }
|
示例2:文件系统类型识别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/vfs.h>
// 常见文件系统类型的宏定义 #define EXT2_SUPER_MAGIC 0xEF53 #define EXT3_SUPER_MAGIC 0xEF53 #define EXT4_SUPER_MAGIC 0xEF53 #define XFS_SUPER_MAGIC 0x58465342 #define NTFS_SB_MAGIC 0x5346544E #define TMPFS_MAGIC 0x01021994 #define PROC_SUPER_MAGIC 0x9FA0 #define SYSFS_MAGIC 0x62656572
// 根据文件系统类型返回字符串描述 const char* get_fs_type_name(long fs_type) { switch (fs_type) { case EXT2_SUPER_MAGIC: return "ext2/ext3/ext4"; case XFS_SUPER_MAGIC: return "XFS"; case NTFS_SB_MAGIC: return "NTFS"; case TMPFS_MAGIC: return "tmpfs"; case PROC_SUPER_MAGIC: return "proc"; case SYSFS_MAGIC: return "sysfs"; default: return "未知文件系统"; } }
int main() { int fd; struct statfs fs_info; const char *test_files[] = {"/etc/passwd", "/proc/version", "/sys/kernel"}; int num_files = sizeof(test_files) / sizeof(test_files[0]); for (int i = 0; i < num_files; i++) { printf("\n=== 检查文件: %s ===\n", test_files[i]); // 打开文件 fd = open(test_files[i], O_RDONLY); if (fd == -1) { perror("open"); printf("跳过此文件\n"); continue; } // 获取文件系统信息 if (fstatfs(fd, &fs_info) == -1) { perror("fstatfs"); close(fd); continue; } // 显示详细信息 printf("文件系统类型代码: 0x%lx\n", fs_info.f_type); printf("文件系统类型名称: %s\n", get_fs_type_name(fs_info.f_type)); printf("最大文件名长度: %ld 字符\n", fs_info.f_namelen); printf("片段大小: %ld 字节\n", fs_info.f_frsize); close(fd); } return 0; }
|
示例3:磁盘空间监控工具
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/vfs.h> #include <string.h>
// 磁盘使用情况结构体 struct disk_usage { char path[256]; double total_gb; double used_gb; double free_gb; double usage_percent; };
// 获取磁盘使用情况 int get_disk_usage(const char *filepath, struct disk_usage *usage) { int fd; struct statfs fs_info; // 打开文件 fd = open(filepath, O_RDONLY); if (fd == -1) { perror("open"); return -1; } // 获取文件系统信息 if (fstatfs(fd, &fs_info) == -1) { perror("fstatfs"); close(fd); return -1; } // 填充使用情况结构体 strncpy(usage->path, filepath, sizeof(usage->path) - 1); usage->path[sizeof(usage->path) - 1] = '\0'; // 计算空间大小(GB) double block_size_gb = (double)fs_info.f_bsize / (1024 * 1024 * 1024); usage->total_gb = fs_info.f_blocks * block_size_gb; usage->free_gb = fs_info.f_bavail * block_size_gb; // 使用 f_bavail 而不是 f_bfree usage->used_gb = usage->total_gb - usage->free_gb; usage->usage_percent = (usage->used_gb / usage->total_gb) * 100; close(fd); return 0; }
// 打印磁盘使用情况(带进度条效果) void print_disk_usage(const struct disk_usage *usage) { printf("路径: %s\n", usage->path); printf("总空间: %.2f GB\n", usage->total_gb); printf("已用空间: %.2f GB\n", usage->used_gb); printf("可用空间: %.2f GB\n", usage->free_gb); // 显示进度条 int bar_width = 50; int filled_width = (int)((usage->usage_percent / 100) * bar_width); printf("使用率: %.1f%% [", usage->usage_percent); for (int i = 0; i < bar_width; i++) { if (i < filled_width) { printf("#"); } else { printf("-"); } } printf("]\n\n"); }
int main() { // 测试不同的文件路径 const char *test_paths[] = { "/", "/home", "/tmp", "/etc/passwd" }; int num_paths = sizeof(test_paths) / sizeof(test_paths[0]); printf("=== 磁盘空间监控工具 ===\n\n"); for (int i = 0; i < num_paths; i++) { struct disk_usage usage; if (get_disk_usage(test_paths[i], &usage) == 0) { print_disk_usage(&usage); } else { printf("无法获取 %s 的磁盘信息\n\n", test_paths[i]); } } return 0; }
|
编译和运行说明
1 2 3
| gcc -o fstatfs_example fstatfs_example.c ./fstatfs_example
|
注意事项
文件系统类型: 不同的文件系统类型有不同的魔数(magic number),可以通过 f_type 字段识别
权限要求: 通常只需要对文件有读权限即可调用此函数
空间计算:
移植性: statfs 结构体在不同系统上可能有差异,如需高移植性可考虑使用 statvfs
性能: 频繁调用此函数可能影响性能,建议缓存结果
这些示例展示了 fstatfs 函数的多种应用场景,从简单的空间信息获取到文件系统类型识别,再到实用的磁盘监控工具,帮助你全面理解这个函数的使用方法。
fstatfs系统调用及示例-CSDN博客