🎈1. inode节点与硬链接
通过上图可以看到,硬链接和源文件引用的是同一个inode节点,并且在inode节点中有一条硬链接计数信息,每当inode被引用一次,这个硬链接计数就会加1,我们可以通过ls命令来查看inode节点信息。我们先建立一个文件以及该文件的硬链接,通过ll命令可以查看文件信息(实际上这些信息就是存在inode节点中的信息)。
可以看到,建立一个硬链接之后,硬链接计数增加了1个。通过ls命令的-i选项可以查看文件的inode节点编号。
硬链接文件和源文件的inode节点编号一样,说明它们引用的是同一个inode节点。
在上图中的目录项中,有一条信息是类型,如果当前是目录的话,可以继续进入下一级目录。简单举个例子,比如说我们使用vi打开当前目录可以得到下面的内容。
这里面的三个条目是当前文件夹下的文件,我们可以通过tree命令查看一下当前文件夹./的目录结构
当我们把光标停在某一文件所在行按回车键就可以查看该文件内容,如果这个文件是目录,就会进入该目录并显示目录下的条目。
比如,进入file.txt文件
进入目录111
🎈2. stat函数与 struct stat 结构体
- 包含头文件
#include <sys/types.h> #include <sys/stat.h> #include <unistd.h>
- 函数原型
int stat(const char *path, struct stat *buf); int fstat(int fd, struct stat *buf); int lstat(const char *path, struct stat *buf);
- 函数功能
Get file status - These functions return information about a file. - 函数参数
- path:指定文件
- buf:buf是一个传出参数,也就是一级指针做输出,我们应该先定义一个结构体变量,并把该变量取地址&传给形参。
struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* inode number */ mode_t st_mode; /* protection 实际上就是权限位 */ nlink_t st_nlink; /* number of hard links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ dev_t st_rdev; /* device ID (if special file) */ off_t st_size; /* total size, in bytes 文件大小 */ blksize_t st_blksize; /* blocksize for file system I/O 块大小 */ blkcnt_t st_blocks; /* number of 512B blocks allocated 块的个数 */ time_t st_atime; /* time of last access 最后访问时间 */ time_t st_mtime; /* time of last modification 最后修改时间 */ time_t st_ctime; /* time of last status change 最后状态改变时间 */ };
- 对于结构体struct stat中的 mode_t st_mode 进行简要介绍(下面并没有全部列出,只列出了部分),首先是判断文件类型的两种方法。第一种是掩码的方式。
S_IFMT 0170000 bit mask for the file type bit fields S_IFSOCK 0140000 socket S_IFLNK 0120000 symbolic link 符号链接 S_IFREG 0100000 regular file 普通文件 S_IFBLK 0060000 block device 块设备 S_IFDIR 0040000 directory 目录 S_IFCHR 0020000 character device 字符设备 S_IFIFO 0010000 FIFO 管道
- 这个实际上就是我们ll命令查看文件时,第一列所显示的文件类型,在上面列出的内容中,中间一列数字用来标识文件类型,从S_IFSOCK到S_IFIFO就是我们所熟知的7种文件类型,S_IFMT是文件类型的掩码。通过和S_IFMT的与运算,就可以把标识文件类型的位保留下来(也就是前两个数017,第一个0表示8进制,后面17共四位 1 111 用来标识文件类型,那么S_IFMT用二进制表示就是1111后面加12个0,通过与与运算就把后面12位置为0而保留代表文件类型的四个bit,再把相与的结果与下面的S_IFSOCK到S_IFIFO进行对比来判断文件类型),进而判断文件类型。比如,现在有一个0041100,把它和S_IFMT做与运算结果为
0041100 & 0170000 = 0040000 (S_IFMT) (S_IFDIR)
- 通过结果对比可以得出这是一个目录文件。这是通过掩码的方式来判断文件类型。
另外一种判断文件类型的方法是使用它为我们提供的宏来判断,7种文件类型判断相关的宏如下所示,这里的m是指stat结构体中的st_mode。
S_ISREG(m) is it a regular file? S_ISDIR(m) directory? S_ISCHR(m) character device? S_ISBLK(m) block device? S_ISFIFO(m) FIFO (named pipe)? S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.) S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
- 最后就是用户、组、其他用户的权限位(4位掩码,第一个0表示8进制)
S_IRWXU 00700 mask for file owner permissions S_IRUSR 00400 owner has read permission S_IWUSR 00200 owner has write permission S_IXUSR 00100 owner has execute permission S_IRWXG 00070 mask for group permissions S_IRGRP 00040 group has read permission S_IWGRP 00020 group has write permission S_IXGRP 00010 group has execute permission S_IRWXO 00007 mask for permissions for others (not in group) S_IROTH 00004 others have read permission S_IWOTH 00002 others have write permission S_IXOTH 00001 others have execute permission
- st_mode 各位含义示意图
- 结构体struct stat中的时间time_t也是一个结构体,它的原型如下
struct timespec { _kernel_time_t tv_sec; /*seconds 当前时间到1970.1.1 0:0:0的秒数*/ long tv_nsec; /*nanoseconds 纳秒*/ }
- 函数返回值
成功返回0,失败返回-1并设置errno 。On success, zero is returned. On error, -1 is returned, and errno is set appropriately.