一、linux文件系统如何存储数据(以ext4为例)?

   我们知道,linux中一切皆文件,文件包括属性内容两部分(当然,还包括文件名,不过件名实质是其所属目录文件的内容,目录文件也有inode号)。linux文件系统将这两类数据分别存储于不同的区域,属性信息放置于inode区(即元数据区)中,实际内容放置于data block区中,另外,还有一个superblock(超级块)会记录整个文件系统的整体信息。

   1、inodeindex node,即索引节点存放文件的属性信息(如文件类型、大小、权限、属主属组、时间戳等)和文件内容所在的block编号

     1)inode是文件惟一标识,系统根据文件名先找到inode,并首先分析是否符合inode中记录的权限,符合后根据block编号找到数据块读取内容。

             

理解inode和文件链接_硬链接


     2)ext4格式的文件系统的每个inode大小为256bytes(之前为128bytes),这在磁盘(或分区)格式化(创建文件系统)时就确定了。inode记录一个block编号占用4byte,故一个inode中所能记录的block编号是有限的,为此,当一个inode不够记录时,可再借用若干个block帮助其记录block编号,并且可以使用多级间接block,如下图:

理解inode和文件链接_硬链接_02


   2、block(块)存放文件实际内容

     1)每个block大小有1K,2K及4K三种,其大小也是在磁盘(或分区)格式化时就确定了,要改变需重新格式化

     2)block大小的差异,会导致该文件系统所能支持的最大磁盘(或分区)容量和最大文件容量不同。block越大,文件系统所能支持的最大磁盘(或分区)容量和最大文件容量也越大

     3)每个block内只能存放一个文件的内容

     4)若文件内容大小大于单个block,则该文件会占用多个block;若占不满一个block,这个block中的剩余空间也将浪费,因此block大小的选取也很重要:

       若经常存储小文件,而block较大无疑会浪费很多空间;但block较小的话,大型文件会占用较多的block数,这样inode中也会记录更多的block编号,由此会降低系统读写性能。所以block大小的选取应根据实际情况权衡


   3、superblock存放此文件系统的整体信息,包括inode/block大小、inode/block总量、使用量、剩余量、文件系统格式等。一个文件系统仅有一个superblock,位于组0中,这个块很重要,因此通常还有一个备份位于其它组中,其大小一般为1K。

     查看超级块信息dumpe2fs [-h] DEVICE,如dempe2fs -h /dev/sda2

                tune2fs -l DEVICE

理解inode和文件链接_软链接_03

     

   4、由于文件系统通常很大,所以将所有inode和block放在一起的话查找起来极为不便,为此ext4文件系统在创建时实际是分成多个组(group)的,组编号从0开始。每个组都有独立的inode/block/superblock系统,这样管理起来就简易多了。

[root@localhost ~]# dumpe2fs /dev/sda2
...
Last mounted on:          /
Filesystem UUID:          b37fe9d5-cef1-4e11-a9a7-b82df4f692f0
...
Inode count:              655360    # inode总数
Block count:              2621440   # block总数
Reserved block count:     131072    # 保留的block数
Free blocks:              1827155   # 可用的block数
Free inodes:              571880    # 可用的inode数
First block:              0
Block size:               4096      # 每个block大小,4K
Fragment size:            4096
Reserved GDT blocks:      639
Blocks per group:         32768     # 每个组的block数
Fragments per group:      32768
Inodes per group:         8192      # 每个组的inode数
Inode blocks per group:   512
Flex block group size:    16
...
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:	          256       # 每个inode的大小
...

Group 0: (Blocks 0-32767) [ITABLE_ZEROED]
  Checksum 0x556c, unused inodes 0
  Primary superblock at 0, Group descriptors at 1-1  # 此组的第0号块为superblock
  Reserved GDT blocks at 2-640
  Block bitmap at 641 (+641), Inode bitmap at 657 (+657)
  Inode table at 673-1184 (+673)
  21647 free blocks, 0 free inodes, 995 directories
  Free blocks: 11121-32767
  Free inodes: 
Group 1: (Blocks 32768-65535) [ITABLE_ZEROED]
  Checksum 0xeac9, unused inodes 0
  Backup superblock at 32768, Group descriptors at 32769-32769  # superblock备份位于此组中
  ...


   5、当我们要创建一个文件时,当然要寻找一个空的inode和若干个空的block,那么哪些inode和block块是空的呢?这时候就需要求助于inodemap(inode位图)bitmap(块位图)了,bitmap用于描述磁盘(或分区)上每个数据块的使用情况。inodemap和bitmap均处于元数据区


   6、设备文件是一类特殊的文件,只有inode而无内容,它们关联至一个驱动程序,进而跟对应的硬件设备打交道



二、文件链接

   1、我们知道,文件名即是通向文件inode的路径,所谓“条条大路通罗马”,指向一个inode的路径当然也可以不止一条。而且,指向一个inode的方式有两种:

     1)A→inode1,B→inode1

       文件名A和B都直接指向同一个inode,这种情况,我们就称A或B为对方的硬链接。自然删除其中一个文件名并不影响另一个文件名的访问。

       ①硬链接是有限制的:不能跨分区;不能对目录建立硬链接 

       ②一个inode可以被引用多次,其有计数器,增加一条路径则加1,删除一条路径则减1,直至降为0,此inode和它指向的磁盘块才被标记为空闲        

       注意:建立硬链接是不同于复制的,硬链接只是增加文件路径而已,而复制是建立一个全新的文件,会在磁盘中占用inode和block块

      2)A→inode1,B→inode2→A→inode1

        B并不直接指向inode1,而是先要通过A。B指向另一个inode2,随后读取到内容为文件名A,由此再指向inode1。这时候,我们称B为A的软链接(符号链接)。自然,删除A后B就无法访问最终目标文件内容。

        ①可以对目录创建软链接,且不受分区限制

               ②创建软链接并不增加inode计数,因为软链接并不直接指向目标inode

     

   2、文件移动:

        在同一个分区移动文件仅是改变文件访问路径,并不改变inode号

        跨分区移动,在新分区创建文件,把数据复制过去,删除原分区数据


   3、使用ln命令建立链接

     用法:ln [option]... SOURCE LINK

     不加任何选项则为建立硬链接

     常用选项:

        -f:建立链接时先将与LINK同档名的文件删除

        -i:在删除与LINK同档名的文件之前先进行询问

        -s:建立软链接

        -d:在建立链接时先将与LINK同档名的文件进行备份 

      注意:建立软链接时指定源文件名要使用绝对路径(若链接文件名与源文件名在同一目录下,还可使用相对路径,否则必须使用绝对路径),因为链接文件直接读取的块内容是源文件名,若源文件名使用相对路径,它将无法再通过这个不完整的路径通达最终文件的inode,如下:

   4、链接文件的默认权限为777,但用户是否能读取文件内容要以源文件的权限为准

[tesla@localhost ~]$ ln shakespear /tmp/literature   # 建立硬链接
[tesla@localhost ~]$ ll -i shakespear /tmp/literature  # 可以看到,链接文件与源文件指向同一个inode(第一列),且inode连结数已变为2
145388 -rw-rw-r-- 2 tesla tesla 39 Oct 10 01:31 shakespear
145388 -rw-rw-r-- 2 tesla tesla 39 Oct 10 01:31 /tmp/literature
[tesla@localhost ~]$ rm -f shakespear 
[tesla@localhost ~]$ ll /tmp/literature 
-rw-rw-r-- 1 tesla tesla 39 Oct 10 01:31 /tmp/literature
[tesla@localhost ~]$ cat /tmp/literature  # 删除源文件名后仍能访问文件内容
To be or not to be,that is a question.
[tesla@localhost ~]$ ln -s heracleitus /tmp/truth   # 因源文件名使用了相对路径,软链接建立失败,见后面
[tesla@localhost ~]$ ll -i heracleitus /tmp/truth
145394 -rw-rw-r-- 1 tesla tesla 42 Oct 10 03:05 heracleitus
393219 lrwxrwxrwx 1 tesla tesla 11 Oct 10 03:11 /tmp/truth -> heracleitus
[tesla@localhost ~]$ cat /tmp/truth   # 无法访问
cat: /tmp/truth: No such file or directory
[tesla@localhost ~]$ ln -s /home/tesla/heracleitus /tmp/truth2  # 重新建立软链接
[tesla@localhost ~]$ ll -i /home/tesla/heracleitus /tmp/truth2  # 可以看到源文件名和链接文件名指向不同inode
145394 -rw-rw-r-- 1 tesla tesla 42 Oct 10 03:05 /home/tesla/heracleitus
397175 lrwxrwxrwx 1 tesla tesla 23 Oct 10 03:16 /tmp/truth2 -> /home/tesla/heracleitus
[tesla@localhost ~]$ cat /tmp/truth2   # 可以访问最终文件内容了
There is nothing permanent except change.
[tesla@localhost ~]$ rm -f /home/tesla/heracleitus
[tesla@localhost ~]$ cat /temp/truth2   # 删除源文件名后无法访问最终文件内容了
cat: /temp/truth2: No such file or directory
[tesla@localhost ~]$ ln -s /etc /home/tesla/test   # 也可对目录创建软链接
[tesla@localhost ~]$ ls test
abrt                   cron.deny ...