struct stat结构体
struct stat
是 C 语言中用于获取文件或文件系统对象属性的结构体,定义在 <sys/stat.h>
头文件中 。它在文件操作和系统编程中非常重要,能提供文件的各种元数据信息。
struct stat结构体定义
struct stat {mode_t st_mode; //文件对应的模式,文件,目录等ino_t st_ino; //inode节点号dev_t st_dev; //设备号码dev_t st_rdev; //特殊设备号码nlink_t st_nlink; //文件的连接数uid_t st_uid; //文件所有者gid_t st_gid; //文件所有者对应的组off_t st_size; //普通文件,对应的文件字节数time_t st_atime; //文件最后被访问的时间time_t st_mtime; //文件内容最后被修改的时间time_t st_ctime; //文件状态改变时间blksize_t st_blksize; //文件内容对应的块大小blkcnt_t st_blocks; //伟建内容对应的块数量};
成员说明
st_dev
- 含义:文件所在设备的 ID。每个设备在系统中都有唯一标识,通过它可判断文件存储在哪个设备上,如硬盘、分区等。
- 示例:在多硬盘系统中,可依据此成员确定文件属于主硬盘还是外接硬盘。
st_ino
- 含义:inode 编号,是文件在其所在文件系统中的唯一标识。inode 包含文件大部分元数据,文件名通过目录项与 inode 关联。
- 示例:用于判断多个文件是否为同一文件的硬链接,具有相同 inode 编号的文件互为硬链接。
st_mode
- 含义:描述文件类型和访问权限。是
mode_t
类型(本质为整数),通过不同位组合表示各种属性。 - 文件类型判断:可通过掩码(如
S_IFMT
)和按位与操作(&
)提取文件类型信息。例如:(st_mode & S_IFMT) == S_IFDIR
判断是否为目录文件。(st_mode & S_IFMT) == S_IFREG
判断是否为普通文件。(st_mode & S_IFMT) == S_IFLNK
判断是否为符号链接文件。
- 权限判断:剩余位表示文件访问权限,分所有者、所属组和其他用户三类,每类都有读(
S_IRUSR
)、写(S_IWUSR
)、执行(S_IXUSR
)权限。例如,st_mode & S_IRUSR
判断所有者是否有读权限。
- 含义:描述文件类型和访问权限。是
st_nlink
- 含义:文件的硬链接数。硬链接是多个文件名指向同一个 inode,增加硬链接数即增加文件别名。
- 示例:删除硬链接时,硬链接数减 1,只有当硬链接数变为 0 时,文件 inode 和实际数据才会被删除,可防止误删数据。
st_uid
和st_gid
- 含义:
st_uid
是文件所有者的用户 ID,st_gid
是文件所有者的组 ID,标识对文件有特定权限的用户和组。 - 示例:系统通过比较用户 ID 与
st_uid
,以及用户所属组 ID 与st_gid
,确定用户或组对文件的访问权限。
- 含义:
st_rdev
- 含义:对于特殊设备文件(如字符设备或块设备文件),表示设备的实际设备 ID;普通文件该值通常为 0。
- 示例:设备驱动程序和内核通过它识别和操作对应的物理设备。
st_size
- 含义:文件大小,以字节为单位。普通文件是实际数据量,目录文件大小通常是目录项大小总和(不同文件系统有差异)。
- 示例:在文件读取、写入、下载或上传时,可根据此值确定操作边界或显示进度。
st_blksize
- 含义:文件系统 I/O 块大小,即文件系统读写操作使用的块大小,不同文件系统默认块大小不同,如 4096 字节。
- 示例:优化文件 I/O 操作时,若每次读写数据量是块大小整数倍,可提高 I/O 效率。
st_blocks
- 含义:分配给文件的块数,反映文件在文件系统中实际占用的物理空间。
- 示例:用于计算文件实际占用磁盘空间大小(块数乘以块大小),对磁盘空间管理和文件存储优化有参考价值。
st_atime
、st_mtime
和st_ctime
- 含义:
st_atime
:文件最后访问时间,即最后一次被读取的时间。st_mtime
:文件最后修改时间,即文件内容最后一次被修改的时间。st_ctime
:文件最后状态改变时间,文件权限、所有者、链接数等元数据改变都会更新此时间。
- 示例:文件备份系统可根据这些时间戳确定哪些文件需备份(如只备份最后修改时间大于上次备份时间的文件);文件系统缓存机制可利用它们判断文件是否被修改,决定是否重新读取文件内容。
- 含义:
st_mode
文件类型标志位
宏定义 | 含义 | 描述 | 判断示例 |
S_IFMT | 文件类型掩码 | 用于提取文件类型部分的位掩码 | (st_mode &S_IFMT) |
S_IFDIR | 目录文件 | 表示该文件是一个目录 | (st_mode &S_IFMT)==S_IFDIR |
S_IFREG | 普通文件 | 表示该文件是一个普通文件(包含文本文件、二进制文件等 ) | (st_mode &S_IFMT)==S_IFREG |
S_IFLNK | 符号链接文件 | 表示该文件是一个符号链接(软链接) | (st_mode &S_IFMT)==S_IFLNK |
S_IFCHR | 字符设备文件 | 用于与按字符流方式进行数据传输的设备相关联,如键盘、串口设备 | (st_mode &S_IFMT)==S_IFCHR |
S_IFBLK | 块设备文件 | 用于与以块为单位进行数据传输的设备相关联,如硬盘、USB存储设备 | (st_mode &S_IFMT)==S_IFBLK |
S_IFSOCK | 套接字文件 | 用于网络通信或本地进程间通信(UNIX域套接字) | (st_mode &S_IFMT)==S_IFSOCK |
S_IFIFO | FIFO(命名管道)文件 | 用于进程间通信,数据以先进先出顺序处理 | (st_mode &S_IFMT)==S_IFIFO |
所属组权限
宏定义 | 含义 | 描述 | 判断示例 |
S_IRGRP | 组读权限 | 文件所属组的成员具有读取文件内容的权限 | st_mode &S_IRGRP为真则组内成员有读权限 |
S_IWGRP | 组写权限 | 文件所属组的成员具有写入或修改文件内容的权限 | st_mode &s_IMGRP为真则组内成员有写权限 |
S_IXGRP | 组执行权限 | 文件所属组的成员具有执行文件的权限(对于可执行文件或脚本) | st_mode &S_IXGRP为真则组内成员有执行权限 |
其他用户权限
宏定义 | 含义 | 描述 | 判断示例 |
S_IROTH | 其他读权限 | 不属于文件所有者和所属组的其他用户具有读取文件内容 的权限 | st_mode &S_IROTH为真则其他用户有读权限 |
S_IWOTH | 其他写权限 | 不属于文件所有者和所属组的其他用户具有写入或修改文 件内容的权限 | st_mode &S_IWOTH为真则其他用户有写权限 |
S_IXOTH | 其他执行权限 | 不属于文件所有者和所属组的其他用户具有执行文件的权 限(对于可执行文件或脚本) | st_mode &S_IXOTH为真则其他用户有执行权限 |
POSIX宏检查st_mode
S_ISREG(m) 常规文件
S_ISDIR (m) 目录
S_ISCHR (m) 字符设备
S_ISBLK (m) 块设备
S_ISFIFO(m) FIFO(命名管道)
S_ISLNK (m) 符号链接
S_ISSOCK (m) 套接字
获取 struct stat
信息的函数
stat
- 原型:
int stat(const char *pathname, struct stat *statbuf);
- 功能:获取指定路径名文件的属性,填充
statbuf
结构体。若路径是符号链接,获取的是链接指向文件的属性。
- 原型:
fstat
- 原型:
int fstat(int fd, struct stat *statbuf);
- 功能:根据已打开文件描述符
fd
获取文件属性,填充statbuf
结构体。常用于已打开文件,获取其相关属性。
- 原型:
lstat
- 原型:
int lstat(const char *pathname, struct stat *statbuf);
- 功能:类似
stat
,但如果路径是符号链接,获取的是符号链接本身的属性,而非链接指向文件的属性
- 原型:
示例代码
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>int main() {struct stat file_stat;if (stat("input.txt", &file_stat) == -1) {perror("stat");return 1;}printf("File size: %lld bytes\n", (long long)file_stat.st_size);printf("Last modified time: %ld\n", (long)file_stat.st_mtime);if (S_ISREG(file_stat.st_mode)) {printf("It's a regular file.\n");} else if (S_ISDIR(file_stat.st_mode)) {printf("It's a directory.\n");}return 0;
}