数据块

转载于骏马金龙

基于上篇文章:文件系统的完整结构 除了Data Blocks,其余的都解释过了。

73301320180727160411876443793371.png

Data Blocks就是直接存储数据的block,但事实并非如此简单。

数据所占用的block由文件对应inode记录中的block指针找到,不同的文件类型,数据block中存储的内容是不一样的。以下是Linux中不同类型文件的存储方式。

  • 对于常规文件,文件的数据正常存储在数据块中。
  • 对于目录,该目录下的所有文件和一级子目录的目录名存储在数据块中。
  • 文件名和inode号不是存储在其自身的inode中,而是存储在其所在目录的data block中。
  • 对于符号链接,如果目标路径名较短则直接保存在inode中以便更快地查找,如果目标路径名较长则分配一个数据块来保存。
  • 设备文件、FIFO和socket等特殊文件没有数据块,设备文件的主设备号和次设备号保存在inode中。

目录文件的data block

目录的data block的内容如下图所示。

xssdsdsdss.png

由图可知,在目录文件的数据块中存储了其下的文件名、目录名、目录本身的相对名称"."和上级目录的相对名称"..",还存储了这些文件名对应的inode号、目录项长度rec_len、文件名长度name_len和文件类型file_type。注意到除了文件本身的inode记录了文件类型,其所在的目录的数据块也记录了文件类型。由于rec_len只能是4的倍数,所以需要使用"\0"来填充name_len不够凑满4倍数的部分。至于rec_len具体是什么,只需知道它是一种偏移即可。

需要注意的是,inode table中的inode自身并没有存储每个inode的inode号(上图只是一个数据块,并不是inode table),它是存储在目录的data block中的,通过inode号可以计算并索引到inode table中找到该inode号对应的inode记录,可以认为这个inode号是一个inode指针(当然,并非真的是指针,但有助于理解通过inode号索引找到对应inode的这个过程,后文将在需要的时候使用inode指针这个词来表示inode号。至此,已经知道了两种指针:一种是inode table中每个inode记录指向其对应的data block的block指针,一个此处的“inode指针”)。

除了inode号,目录的data block中还使用数字格式记录了文件类型,数字格式和文件类型的对应关系如下图。

55555555555555555.png

注意到目录的data block中前两行存储的是目录本身的相对名称"."和上级目录的相对名称"..",它们实际上是目录本身的硬链接和上级目录的硬链接。硬链接的本质后面说明。

如何根据inode号找到inode

前面提到过,inode结构自身并没有保存inode号(同样,也没有保存文件名),那么inode号保存在哪里呢?目录的data block中保存了该目录中每个文件的inode号。

另一个问题,既然inode中没有inode号,那么如何根据目录data block中的inode号找到inode table中对应的inode呢?

实际上,只要有了inode号,就可以计算出inode表中对应inode号的inode结构。在创建文件系统的时候,每个块组中的起始inode号及inode table的起始地址都已经确定,所以只要知道了inode号,就能直到这个inode号和该起始inode号的偏移数量,再根据每个inode结构的大小(256字节或其他大小),就能计算出来对应的inode结构。

所以,目录的data block中的inode number和inode table中的inode是通过计算的方式一一映射起来的。从另一个角度上看,目录data block中的inode number是找到inode table中对应inode记录的唯一方式。

考虑一种比较特殊的情况:目录data block的记录已经删除,但是该记录对应的inode结构仍然存在于inode
table中。这种inode称为孤儿inode(orphan inode):存在于inode table中但却无法再索引到它。因为目录中已经没有该inode对应的文件记录了,所以其它进程将无法找到该inode,也就无法根据该inode找到该文件之前所占用的data block,这正是创建便删除所实现的真正临时文件,该临时文件只有当前进程和子进程才能访问。

符号链接存储方式

符号链接即为软链接,类似于Windows中的快捷方式,它的作用是指向源文件或目录。

软链接之所以被称为特殊文件的原因是:它一般情况下不占用data block,仅仅通过它对应的inode记录就能将信息描述完成;符号链接的大小是其指向目标路径占用的字符个数,例如某个符号链接的指向方式为"rmt --> ../sbin/rmt",则其文件大小为11字节;只有当符号链接指向的目标的路径名较长(60个字节)时文件系统才会划分一个data block给它;它的权限如何也不重要,因它只是一个指向原文件的"工具",最终决定是否能读写执行的权限由原文件决定,所以很可能ls -l查看到的符号链接权限为777。

注意,软链接的block指针(存储于inode中指向block的指针)存储的是目标文件名。也就是说,链接文件的一切都依赖于其目标文件名。这就解释了为什么/mnt的软链接/tmp/mnt在/mnt挂载文件系统后,通过软链接就能进入/mnt所挂载的文件系统。究其原因,还是因为其目标文件名"/mnt"并没有改变。

例如以下筛选出了/etc/下的符号链接,注意观察它们的权限和它们占用的空间大小。

root@generalai-cpu-0:~/go/src/k8sMLer-client-go# ll /etc/ | grep '^l'
lrwxrwxrwx   1 root root         27 Jan 29 14:40 localtime -> /usr/share/zoneinfo/Etc/UTC
lrwxrwxrwx   1 root root         19 Jan 25 23:55 mtab -> ../proc/self/mounts
lrwxrwxrwx   1 root root         21 Aug 14  2020 os-release -> ../usr/lib/os-release
lrwxrwxrwx   1 root root         29 Jan 30 13:12 resolv.conf -> ../run/resolvconf/resolv.conf
lrwxrwxrwx   1 root root         23 Jan 25 23:54 vtrgb -> /etc/alternatives/vtrgb

设备文件、FIFO、套接字文件

关于这3种文件类型的文件只需要通过inode就能保存它们的信息,它们不占用任何数据块,所以它们是特殊文件。

设备文件的主设备号和次设备号也保存在inode中。以下是/dev/下的部分设备信息。注意到它们的第5列和第6列信息,它们分别是主设备号和次设备号,主设备号标识每一种设备的类型,次设备号标识同种设备类型的不同编号;也注意到这些信息中没有大小的信息,因为设备文件不占用数据块所以没有大小的概念。

root@generalai-cpu-0:~/go/src/k8sMLer-client-go#  ll /dev | tail
crw-rw----  1 root tty       7, 134 May 11 14:19 vcsa6
brw-rw----  1 root disk    252,   0 May 11 14:19 vda
brw-rw----  1 root disk    252,   1 May 11 14:19 vda1
brw-rw----  1 root disk    252,  14 May 11 14:19 vda14
brw-rw----  1 root disk    252,  15 May 11 14:19 vda15
drwxr-xr-x  2 root root          60 May 11 14:19 vfio/
crw-------  1 root root     10,  63 May 11 14:19 vga_arbiter
crw-------  1 root root     10, 238 May 11 14:19 vhost-net
crw-------  1 root root     10, 241 May 11 14:19 vhost-vsock
crw-rw-rw-  1 root root      1,   5 May 11 14:19 zero
    评论
    0 评论
avatar

取消