1.stat
假设一个路径是/opt/file,则查找的顺序是:
①读出inode表中第2项(根目录inode),从中找出根目录数据块位置。
②从根目录数据块找出文件名为opt的记录,从记录中读出inode号。
③读出opt目录的inode,从中找出它的数据块位置。
④从opt目录的数据块中找出文件名为file的记录,从记录中读出inode号。
⑤读出file文件的inode。
另外还有系统和inode相关的系统调用:
2.opendir(3)/readdir(3)/closedir(3)
用于遍历目录数据块中的记录。
opendir:打开一个目录,返回一个Dir *指针代表这个目录,类似FILE *指针的句柄。
closedir:关闭这个句柄,把Dir *指针传给readdir读取目录数据块中的记录,每次返回一个指向struct dirent的指针,反复读可以遍历所有记录,所有记录遍历完之后readdir返回NULL。
结构体struct dirent定义:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <unistd.h>
void printDir(char *dirname) {
char pathname[1024];
DIR *dir;
struct dirent *dp;
struct stat st;
if (!(dir=opendir(dirname))) {
perror("opendir");
exit(1);
}
while (dp = readdir(dir))
{
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) {
continue;
}
sprintf(pathname, "%s/%s", dirname, dp->d_name);
if (stat(pathname, &st) < 0) {
perror("stat");
exit(1);
}
if (S_ISDIR(st.st_mode)) {
printDir(pathname);
}
printf("%s\t", dp->d_name);
}
putchar(10);
closedir(dir);
}
int main(int argc, char **argv) {
if (argc < 2) {
printf("usage:cmd + path");
return 1;
}
printDir(argv[1]);
return 0;
}
3.VFS
Virtual Filesystem
Linux支持各种各样文件系统格式,然后这些文件系统都可以mount到某个目录下,使我们看到一个统一目录树,各种文件系统上的目录和文件用ls命令看是一样的,读写操作是一样的,这是如何做到的?
Linux内核在各种不同的文件系统格式之上做了一个抽象层,使文件,目录,读写访问等概念称为抽象层概念,因此各种系统看起来用起来都一样,这个抽象层为虚拟文件系统。
4.dup和dup2
都可用来复制一个现存的文件描述符,使两个文件描述符指向同一个file结构体。
如果两个文件描述符指向同一个file结构体,File,Status,Flag和读写位置只保存一份在file结构体,并且file结构体的引用计数是2.
如果两次open同一文件得到两个文件描述符,则每个描述符对应一个不同的file结构体,可以有不同的File,Status,Flag和读写位置。
区分这两种情况:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
int main(void) {
int fd, save_fd;
if ((fd = open("test.txt", O_RDWR)) < 0) {
perror("open");
exit(1);
}
save_fd = dup(1);
dup2(fd, 1);
close(fd);
write(1, "123456789", 9);
dup2(save_fd, 1);
write(1, "123456789", 9);
close(save_fd);
return 0;
}