1.4 文件系统

Xv6文件系统提供数据文件(包含未解释的字节数组)和目录(包含对数据文件和其他目录的命名引用)。这些目录形成一个树,从一个叫做根的特殊目录开始。像/a/b/c这样的路径是指在根目录/下名为a的目录中名为b的目录中名为c的文件或目录。不以/开始的路径相对于调用进程的当前工作目录进行计算,当前工作目录可以通过chdir系统调用进行更改。下面两个代码片段打开相同的文件(假设所有相关的目录都存在)

chdir("/a");
chdir("b");
open("c", O_RDONLY);
open("/a/b/c", O_RDONLY);

上面代码将进程的当前目录更改为/a/b;下面代码既不引用也不更改进程的当前目录

还有创建新文件和目录的系统调用:

  • mkdir创建一个新目录

  • open中若使用O_CREATE标志将会创建一个新的数据文件

  • mknod创建一个新的设备文件

这个例子说明了这三点:

mkdir("/dir");
fd = open("/dir/file", O_CREATE | O_WRONLY);
close(fd);
mknod("/console", 1, 1);

mknod创建一个引用设备的特殊文件。与设备文件相关联的是主设备号和次设备号(mknod的两个参数),它们唯一地标识了一个内核设备。当进程稍后打开设备文件时,内核将使用内核设备实现readwrite系统调用,而不是使用文件系统。

一个文件的名字和文件本身是不同的;同一个底层文件(叫做inode,索引结点)可以有多个名字(叫做link,链接)。每个链接都由目录中的一个条目组成;该条目包含一个文件名和一个inode引用。Inode保存有关文件的元数据(用于解释或帮助理解信息的数据),包括其类型(文件/目录/设备)、长度、文件内容在磁盘上的位置以及指向文件的链接数。

fstat系统调用从文件描述符所引用的inode中检索信息。它填充一个stat类型的结构体,struct statstat.h(kernel/stat.h)中定义为

#define T_DIR 1    // Directory
#define T_FILE 2   // File
#define T_DEVICE 3 // Device
struct stat {
    int dev;     // 文件系统的磁盘设备
    uint ino;    // Inode编号
    short type;  // 文件类型
    short nlink; // 指向文件的链接数
    uint64 size; // 文件字节数
};

link系统调用创建另一个文件名,该文件名指向与现有文件相同的inode。下面的代码片段创建了一个名字既为a又为b的新文件

open("a", O_CREATE | O_WRONLY);
link("a", "b");

a读取或写入与从b读取或写入是相同的操作。每个inode由唯一的inode编号标识。在上面的代码序列之后,可以通过检查fstat的结果来确定a和b引用相同的底层内容:两者都将返回相同的inode号(ino),并且nlink计数将被设置为2。

unlink系统调用从文件系统中删除一个名称。只有当文件的链接数为零且没有文件描述符引用时,文件的inode和包含其内容的磁盘空间才会被释放,因此添加

unlink("a");

最后一行代码序列中会使inode和文件内容可以作为b访问。此外

fd = open("/tmp/xyz", O_CREATE | O_RDWR);
unlink("/tmp/xyz");

是创建没有名称的临时inode的惯用方法,该临时inode将在进程关闭fd或退出时被清理。

Unix以用户级程序的形式提供了可从shell调用的文件实用程序,例如mkdirlnrm。这种设计允许任何人通过添加新的用户级程序来扩展命令行接口。事后看来,这个计划似乎是显而易见的,但是在Unix时代设计的其他系统经常将这样的命令构建到shell中(并将shell构建到内核中)

一个例外是cd,它是内置在shell(user/sh.c:160)。cd必须更改shell本身的当前工作目录。如果cd作为常规命令运行,那么shell将分出一个子进程,子进程将运行cdcd将更改子进程的工作目录。父目录(即shell的)的工作目录不会改变。

copyright by duguosheng all right reserved,powered by Gitbook该文件修订时间: 2021-08-18 12:04:10

results matching ""

    No results matching ""