文件

重点内容,需熟练掌握文件的物理结构,也需了解文件的元信息和逻辑结构,常在选择题中考察,也会在大题中考察。

文件元信息

在UNIX和类UNIX操作系统中,inode(索引节点)是一个非常重要的数据结构,用于表示文件系统中的文件和目录。每个文件或目录都有一个与之对应的inode,它包含了关于该文件的大部分元数据,但不包括文件名和文件实际内容。

inode信息

  • 文件类型:文件是普通文件、目录还是链接文件等。
  • 权限:文件的访问控制信息,如用户、组和其他用户的读、写、执行权限。
  • 所有者:文件的所有者和组ID。
  • 大小:文件的大小(字节数)。
  • 时间戳:文件的创建时间、最后修改时间和最后访问时间。
  • 链接计数:指向该文件的硬链接数量。当计数为0时,文件会被删除。
  • 数据块指针:文件内容所在的数据块(block)的位置信息。这包括直接指针、间接指针、二级间接指针和三级间接指针,用于指向存储文件内容的磁盘块。

进程文件管理

  • 文件描述符表:每个进程都有自己的文件描述符表,这个表对应于该进程打开的文件描述符。文件描述符是进程范围内的一个小的非负整数。
  • 文件表:操作系统维护一个全局的文件表,该表记录了所有打开文件的状态信息。每次 open 调用成功时,都会创建一个新的文件表条目。
  • inode表:系统还维护了一个inode表,该表包含了文件的元数据和指向文件实际数据的指针。如果多个进程打开同一个文件,它们的文件表条目将指向inode表中的同一inode。

在进程1中执行fdA1 = open("fileA.txt", O_RDONLY)fdAdup = dup(fdA)系统调用,在进程2中执行fdA2 = open("fileA.txt", O_RDONLY),系统中的数据结构如下图所示:

file descriptor
file pointer
fdA1
1
file descriptor
file pointer
fdA2
3
fdAdup
1
file offset
access mode
reference count
inode pointer
0
O_RDONLY
2
4
1
O_RDONLY
1
4
0
1
2
3
4
5
file type
file locks
file properties
Regular
...
...
0
1
2
3
4
5
6
Process A File Descriptor Table
Process B File Descriptor Table
Open File Table
Inode Table

文件的逻辑结构

  1. 顺序文件
    • 记录顺序:顺序文件中的数据以记录的顺序排列。每个记录都按顺序存储在文件中,一个接一个。
    • 访问方式:顺序文件通常按照记录的顺序进行访问。要查找或修改文件中的某个记录,必须从文件的开头开始逐个读取记录,直到找到所需的记录或到达文件末尾。
    • 应用场景:适用于需要按顺序读取和处理数据的应用程序,如批处理任务和日志文件。
  2. 随机文件(或称为索引文件)
    • 记录随机排列:在随机文件中,数据记录可以按任意顺序排列,而不需要按照特定的顺序。
    • 访问方式:随机文件支持随机访问,这意味着可以直接访问文件中的任何记录,而不必按照顺序逐个读取。
    • 索引结构:为了支持随机访问,随机文件通常使用索引结构(如哈希表或B树)来跟踪记录的位置。
    • 应用场景:适用于需要快速查找和访问特定记录的应用程序,如数据库系统和文件系统。

文件的物理结构

1. 连续分配方案(Contiguous Allocation)

连续分配该方案中,每个文件占用磁盘上一个连续的块集。例如,如果一个文件需要n个块,并且给定一个块b作为起始位置,那么分配给该文件的块将是b, b+1, b+2,……b+n-1。这意味着给定起始块地址和文件的长度,我们可以确定文件占用的块。具有连续分配的文件的目录条目包含分配部分的起始块长度的地址。

连续分配方案对应的目录包含如下信息:

  • 文件的其实地址
  • 分配块数量

下图中的文件 “file3” 从区块19开始,长度为6个区块。因此,它占用19、20、21、22、23、24个块。

0
1
2
3
4
5
6
7
8
9
10
3
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
file
start
length
file1
0
2
file2
14
3
file3
19
6
file4
28
4
file5
6
2
Directory
  • 优点:因为由于文件块的连续分配,查找的次数很少,访问速度非常快。
  • 缺点:存在内部和外部碎片化的问题,使得内存利用效率低下。增加文件大小困难,因为它取决于特定实例中连续内存的可用性。

2. 基于链表的分配(Linked List Allocation)

在这个方案中,每个文件都是一个不需要连续的磁盘块链表。磁盘块可以分散在磁盘上的任何地方。目录项包含指向起始和结束文件块的指针。每个块包含一个指针,指向文件所占用的下一个块。

目录项包含指向起始和结束文件块的指针。每个块包含一个指针,指向文件所占用的下一个块。

下图中的文件 “file1” 显示了块是如何随机分布的。最后一个块(25)包含-1,表示空指针,不指向任何其他块。

0
1:10
2
3
4
5
6
7
8
9:16
10:25
3
12
13
14
15
16:1
17
18
19
20
21
22
23
24
25:-1
26
27
28
29
30
31
file
start
end
file1
9
25
Directory
  • 优点:可以充分利用磁盘空间,不会遭遇到碎片的问题。
  • 缺点:因为文件是在磁盘上随机分配的,所以访问一个文件的过程需要经历多次磁盘的检索,这使得文件读取的速度变慢。

3. 基于文件分配表(File Allocation Table)的分配

基于链表的链接为隐式链接,每个磁盘块的末尾包含文件的下一个盘块号。

文件分配表FAT也是基于链接的方式,不过文件的链接方式是存储在一个表格当中,表格包含两列,一列是盘块号,另一列是在该文件盘块之后的下一个盘块号,这种方式也叫做显式链接。

FILENAME
· · · · · ·
START
file1
· · · · · ·
2
file2
· · · · · ·
7
BLOCK NUM
START
0
-2
1
-1
2
8
3
-2
4
-2
5
-1
6
-2
7
1
8
5
9
-2
· · · ·
· · · · 
98
-2
99
-2

4. 索引分配(Index Allocation)

在这个方案中,一个称为Index块的特殊块包含指向文件所占用的所有块的指针。每个文件都有自己的索引块。索引块中的第i项包含第i个文件块的磁盘地址。目录条目包含索引块的地址,如下图所示:

0
1
2
3
4
5
6
7
8
9
10
3
12
13
14
15
16
17
18
20
21
22
23
24
25
26
27
28
29
30
31
file
start
end
file1
9
25
Directory
19

如果文件非常大的话,可以使用多级索引的方式来存储文件所在盘块。

  • 优点:克服了磁盘碎片的问题。
  • 缺点:对于非常小的文件,比如只扩展2-3个块的文件,索引分配将为指针保留一个完整的块(索引块),这样索引块中的很多空间都没有使用,这在内存利用率方面是低效的。

5. 混合索引

还有一种混合索引的方式,可以解决上述提到的缺点,这种方式针对小文件或者大文件进行不同的处理。如果文件比较小的话,使用直接块即可(文件的inode中会包含直接块的下标),如果文件比较大的话,可以使用单级或多级索引。

UNIX系统采用的就是这种方式。

mode
owners(2)
timestamps(3)
size block count
direct blocks
single indirect
double indirect
triple indirect
data
data
data
data
data
data
data
data