(一)文件的状态
主要通过stat
函数获取文件状态,文件通过pathname
获取,而返回的信息通过一个struct stat*
得到,
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
区别在与Path给出了文件的目录,Fd表示已经打开的文件。
该结构体如下:
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 filesystem 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 */
};
常用的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
S_ISUID 0004000 // set-user-ID bit
S_ISGID 0002000 // set-group-ID bit (see below)
S_ISVTX 0001000 // sticky bit (see below)
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
对于文件权限,可以使用S_IRGRP|S_IROTH|S_IRUSR|S_IWUSR
,也可以使用八进制如0644
一个示例
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main(int argc, char *argv[])
{
const char * const PATHNAME = "/home/zhangxiao/zxtest/pipe/myfifo";//关联的路径名
struct stat sb1;
struct stat sb;
int fd= socket(AF_INET,SOCK_STREAM,0);
assert(fd>0);
if (fstat(fd, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
if (stat(PATHNAME, &sb1) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
printf("fd1 File type: ");
switch (sb.st_mode & S_IFMT) {
case S_IFBLK: printf("block device\n"); break;
case S_IFCHR: printf("character device\n"); break;
case S_IFDIR: printf("directory\n"); break;
case S_IFIFO: printf("FIFO/pipe\n"); break;
case S_IFLNK: printf("symlink\n"); break;
case S_IFREG: printf("regular file\n"); break;
case S_IFSOCK: printf("socket\n"); break;
default: printf("unknown?\n"); break;
}
printf("fd2 File type: ");
switch (sb1.st_mode & S_IFMT) {
case S_IFBLK: printf("block device\n"); break;
case S_IFCHR: printf("character device\n"); break;
case S_IFDIR: printf("directory\n"); break;
case S_IFIFO: printf("FIFO/pipe\n"); break;
case S_IFLNK: printf("symlink\n"); break;
case S_IFREG: printf("regular file\n"); break;
case S_IFSOCK: printf("socket\n"); break;
default: printf("unknown?\n"); break;
}
return 0;
}
结果如下:
(二)文件系统
几个关键的概念,inode节点,链接计数,硬链接,符号链接(软链接)等
操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个”块”(block)。这种由多个扇区组成的”块”,是文件存取的最小单位。”块”的大小,最常见的是4KB,即连续八个 sector组成一个 block。
文件数据都储存在”块”中,那么很显然,我们还必须找到一个地方储存文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为”索引节点”。
inode包含文件的元信息:
* 文件的字节数
* 文件拥有者的User ID
* 文件的Group ID
* 文件的读、写、执行权限
* 文件的时间戳,共有三个:ctime指inode上一次变动的时间,mtime指文件内容上一次变动的时间,atime指文件上一次打开的时间。
* 链接数,即有多少文件名指向这个inode
* 文件数据block的位置
除了文件的存储位置以外,其他的属性与stat
返回的结果类似。
(1)普通文件
而同一个inode节点可能有多个指向他的目录项,这就增加了其链接计数,这就是所谓的硬链接,其工作原理有点像shared_ptr
PS:目录块中的目录项,包括inode节点编号和文件名。
另外一种链接叫做软链接也叫符号链接,符号链接文件的实际内容,包含了该符号链接所指向的文件的名字,符号链接就像是普通指针,保存对象的地址。
因此,软链接不能脱离他链接的对象而存在。
(2)目录
对于一个empty目录来说,他的链接计数至少为2,这个数字的怎么来的呢?
首先,对于任何一个空的文件夹来说,他至少包含./
和../
,其中一个链接计数来自于此,
另外,命名该目录(例如empty)的目录项也会为链接计数贡献一点。
如果一个目录中至少包含一个目录,那么他的链接技术至少为3,其实也很好理解,除了上述的2以外,在其子目录中的../
目录项也会为其链接计数贡献一点。
(3)硬链接和软链接设置与查看
现在知道了概念, 那么怎么设置和查看硬链接和软链接?
设置硬链接
ln a b
设置软链接
ln -s a b
查看硬链接
先通过ls -i
找到inode节点号,再用find
查看软链接
直接ls -l
(三) 参考
1.APUE
2.Linux man