1. 目录项与 Inode
1.1 Inode
在 Linux 文件系统中,每个文件(或目录)都有一个对应的 inode(index node) ,即索引节点。inode 不包含文件的名称,而是存储文件的元数据(metadata),例如:
文件大小
设备 ID
文件所有者及所属组的 ID
文件权限(读、写、执行)
时间戳(创建时间、最后访问时间、最后修改时间等)
指向文件数据块的指针
inode 通过一个唯一的编号(inode number)来标识。可以使用 ls -i
命令查看文件的 inode 号:
也可以使用 stat
命令直接查看文件的元数据:
1.2 目录项
目录项(dentry) 是内核用于维护文件系统目录结构的数据结构。每个目录项包含 一个文件名 和 对应的 inode 号 。目录项 将可读的文件名映射到内核使用的 inode 号 。
当用户打开一个文件(如 /home/user/test.txt
)时,内核会遍历路径中的每个目录项,逐步解析直到找到目标文件的 inode,进而访问文件内容。
目录项和 inode 的设计使得文件系统 支持硬链接 。多个目录项可以指向同一个 inode,即同一个文件可以有多个不同的路径名称。
2. stat 函数
2.1 stat 函数原型
stat
函数是一个系统调用,用于 获取指定路径文件的元数据信息 。其原型如下:
1 2 3 4 5 #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int stat (const char *pathname, struct stat *statbuf) ;
pathname
:目标文件的路径。
statbuf
:指向 struct stat
结构的指针,用于存储获取到的文件信息。
2.2 struct stat 结构
struct stat
包含了文件的多种元数据,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 struct stat { dev_t st_dev; ino_t st_ino; mode_t st_mode; nlink_t st_nlink; uid_t st_uid; gid_t st_gid; dev_t st_rdev; off_t st_size; blksize_t st_blksize; blkcnt_t st_blocks; time_t st_atime; time_t st_mtime; time_t st_ctime; };
在 <sys/stat.h>
头文件中定义了一系列宏,用于检测 struct stat
结构中的 st_mode
字段,从而 确定文件类型 。这些宏接受一个 mode_t
类型的参数(通常是 st_mode
字段),并返回一个布尔值。
文件类型相关的宏 :
S_ISREG(m) - 检测是否为普通文件
S_ISDIR(m) - 检测是否为目录
S_ISCHR(m) - 检测是否为字符设备文件
S_ISBLK(m) - 检测是否为块设备文件
S_ISFIFO(m) - 检测是否为 FIFO(命名管道)
S_ISLNK(m) - 检测是否为符号链接
S_ISSOCK(m) - 检测是否为套接字文件
2.3 代码示例
例如,可以使用 stat
获取文件大小、文件类型(文件类型需要用到相关的宏)等:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <stdio.h> #include <sys/stat.h> #include <unistd.h> int main (int argc, char * argv[]) { struct stat stat_buf ; if (stat(argv[1 ], &stat_buf) == -1 ){ perror("stat error" ); return 1 ; } printf ("File size: %lld bytes\n" , (long long )stat_buf.st_size); if (S_ISLNK(stat_buf.st_mode)){ printf ("%s is a sym link\n" , argv[1 ]); } return 0 ; }
注意 :如果 pathname
是一个符号链接,stat
会 跟随链接指向最终的目标文件 (链接穿透),并返回目标文件的元数据。
3. lstat 函数
3.1 lstat 函数原型
lstat
函数与 stat
类似,在处理符号链接时有所不同 。函数原型如下:
1 2 3 4 5 #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int lstat (const char *pathname, struct stat *statbuf) ;
3.2 与 stat 的区别
当路径指向一个符号链接时:
stat
返回 符号链接所指向的目标文件 的元数据。
lstat
返回 符号链接文件本身 的元数据。
3.3 代码示例
以下示例比较 stat
和 lstat
对符号链接的处理:
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 #include <stdio.h> #include <sys/stat.h> #include <unistd.h> int main (int argc, char * argv[]) { struct stat stat_buf ; struct stat lstat_buf ; if (stat(argv[1 ], &stat_buf) == -1 ){ perror("stat error" ); return 1 ; } if (lstat(argv[1 ], &lstat_buf) == -1 ){ perror("lstat error" ); return 1 ; } printf ("stat - inode number of target: %ld\n" , (long )stat_buf.st_ino); if (S_ISLNK(stat_buf.st_mode)){ printf ("stat: %s is a sym link\n" , argv[1 ]); } printf ("lstat - inode number of link itself: %ld\n" , (long )lstat_buf.st_ino); if (S_ISLNK(lstat_buf.st_mode)){ printf ("lstat: %s is a sym link\n" , argv[1 ]); } return 0 ; }