fstatfs 函数详解
函数介绍
fstatfs 是 Linux 系统中用于获取文件系统统计信息的系统调用。可以把这个函数想象成一个”文件系统体检工具”——当你给它一个已打开的文件描述符时,它会告诉你这个文件所在文件系统的详细信息,比如总空间多大、已用多少、还剩多少、支持什么特性等等。
就像你去体检时医生会检查你的身高、体重、血压等指标一样,fstatfs 会检查文件系统的”健康状况”和”基本信息”。
函数原型
1 2 3 4 #include <sys/vfs.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; long f_ffree; fsid_t f_fsid; 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); 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' ; 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; 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博客
相关阅读