计算机操作系统作为最重要的系统软件,被用户直接使用的部分就是它的文件管理。因为用户使用计算机遇到的首要问题是如何保存程序和数据,然后如何查找、复制、删改它们。文件管理就是为用户的这些问题而设置的。


本次博文的主要内容:

1、文件系统基础(文件的概念、分类及存储机制)

2、从文件系统管理机制角度理解文件的复制、移动和删除

3、ext文件系统的扩展属性

4、硬链接和软链接


一、文件系统基础:

1、什么是文件系统:

操作系统中负责管理和存取文件信息的软件机构叫做文件系统。文件系统的目标是向用户提供简便、统一的使用文件的界面,实现文件按名存取。用户使用界面中的命令,按照文件的逻辑结构,直观、透明地对文件实施操作(所谓透明,是指用户不必了解文件存放的物理结构、查找方法、I/O实现细节等与存储介质有关的特性,就能完成对文件的有关操作)

2、文件系统的分类:

操作系统的文件系统按组成单位分为两类:

(1)流式文件:构成流式文件的基本单位是字符,即流式文件是具有符号名且在逻辑意义上完整的有穷字符流序列。如Linux、UNIX、OS/2、windows等都采用流式文件形式。

(2)记录式文件:构成记录式文件的基本单位是记录,所谓记录,是一段有独立意义的信息集合。如学生成绩文件,是由全部学生的成绩记录组成的,每个记录包括学生的姓名、学号、各科成绩等多个字段。

3、Linux系统中的文件类型:

  Linux系统中,文件被分为3类:

(1)目录文件:全部由目录组成的文件

(2)普通文件:由系统文件、用户文件、实用程序文件、库文件组成

(3)特别文件:所有的输入/输出设备被看作特别文件,系统指定专用的文件名,如:/dev/lp表示打印机设备。

4、虚拟文件系统:VFS(Virtual File System)

在前面的博文中已经提到,Linux系统支持众多文件系统,那它是如何做到的呢?

【答】通过虚拟文件系统VFS,使得Linux系统可以支持众多文件系统,这种机制有点类似java的虚拟机机制哈,通过虚拟机机制才使得java能够跨平台!

5、Linux系统ext文件系统的管理机制:

Linux运维实战之文件系统、链接文件_第1张图片

Linux中文件系统存取文件的过程说明

(1)根据文件名,通过Directory里的对应关系,找到文件对应的Inode number
(2)再根据Inode number读取到文件的Inode table
(3)再根据Inode table中的Pointer读取到相应的Blocks

Tips:

A、这里有一个重要的内容,就是Directory(目录),它并不是存放文件的容器,而是文件的路径映射,记录了一个文件/目录名称对应的Inode number;

B、每个Inode条目占用128个字节;

C、为了加速文件的查找速度,第一次需要查找,之后系统会把查找结果缓存到buffer中;事实上,系统启动时会把大多数文件缓存到buffer中(这就是buffer的意义)

文件存储空间管理

光盘、磁盘、磁带等是保存文件内容的物理设备,它们被划分成物理块(block),全部的物理块组成文件的存储空间。文件存储空间的管理就是块空间的管理,包括空闲块的分配、回收和组织几个问题。

常见的文件存储空间管理方法有:空闲块表和空闲块链、位图、空闲块成组链接法。Linux综合位图和空闲块成组链接法来实现文件存储空间的管理(如图所示):

Linux运维实战之文件系统、链接文件_第2张图片

每个块组所包含的Block数相同,它们是自我管理的,其组成说明如下:

(1)Super Block(超级块)-->只有块组0中有超级块

  • 描述整个分区的文件系统信息,例如块大小、文件系统版本号、上次mount的时间等等。
  • 超级块在块组1、3、5、7、9上有一个备份;

文件系统相关命令

  • 用tune2fs –l 和 dumpe2fs [-h] 可查看超级块信息
  • du:disk usage

    -s: summary,显示某指定路径下所有文件的大小之和;
    -h:human-readale

  • df: disk free
        -l: 只显示本地文件系统的相关信息
        -h: human-readable
        -P: posix兼容的风格显示;
        -i: 显示inode使用信息,而非1k块
#----tune2fs -l 命令查看超级块信息-----#

[root@Centos ~]# tune2fs -l /dev/sda1
tune2fs 1.41.12 (17-May-2010)
Filesystem volume name:   
Last mounted on:          /boot
Filesystem UUID:          0a800a5e-6e0b-48f6-b935-1296b7438b64
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super huge_file uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash 
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              51200         #inode数目
Block count:              204800        #块数目
Reserved block count:     10240
Free blocks:              149802        #空闲块数
Free inodes:              51160         #空闲inode
First block:                1
Block size:               1024          #块大小
Fragment size:            1024
Reserved GDT blocks:      256
Blocks per group:         8192        #每个块组的块数
Fragments per group:      8192
Inodes per group:         2048
Inode blocks per group:   256
Flex block group size:    16
Filesystem created:       Wed Jan 29 05:20:48 2014
Last mount time:          Mon Sep 22 21:01:04 2014
Last write time:          Mon Sep 22 21:01:04 2014
Mount count:              19
Maximum mount count:      -1
Last checked:             Wed Jan 29 05:20:48 2014
Check interval:           0 ()
Lifetime writes:          162 MB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:               128        #inode大小
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      30a7a5f3-de5b-4d07-b512-ddb52100b427
Journal backup:           inode blocks
#----dumpe2fs命令查看超级块信息----#

[root@Centos ~]# dumpe2fs /dev/sda1
dumpe2fs 1.41.12 (17-May-2010)
Filesystem volume name:   
Last mounted on:          /boot
Filesystem UUID:          0a800a5e-6e0b-48f6-b935-1296b7438b64
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super huge_file uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash 
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              51200
Block count:              204800
Reserved block count:     10240
Free blocks:              149802
Free inodes:              51160
First block:              1
Block size:               1024
Fragment size:            1024
Reserved GDT blocks:      256
Blocks per group:         8192
Fragments per group:      8192
Inodes per group:         2048
Inode blocks per group:   256
Flex block group size:    16
Filesystem created:       Wed Jan 29 05:20:48 2014
Last mount time:          Mon Sep 22 21:01:04 2014
Last write time:          Mon Sep 22 21:01:04 2014
Mount count:              19
Maximum mount count:      -1
Last checked:             Wed Jan 29 05:20:48 2014
Check interval:           0 ()
Lifetime writes:          162 MB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:               128
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      30a7a5f3-de5b-4d07-b512-ddb52100b427
Journal backup:           inode blocks
Journal features:         journal_incompat_revoke
Journal size:             4096k
Journal length:           4096
Journal sequence:         0x000000a8
Journal start:            0


Group 0: (Blocks 1-8192) [ITABLE_ZEROED]         #块组0的信息
  Checksum 0xf7f8, unused inodes 2006
  Primary superblock at 1, Group descriptors at 2-2        #超级块信息
  Reserved GDT blocks at 3-258
  Block bitmap at 259 (+258), Inode bitmap at 275 (+274)
  Inode table at 291-546 (+290)
  3784 free blocks, 2008 free inodes, 6 directories, 2006 unused inodes
  Free blocks: 4409-8192
  Free inodes: 40, 42-2048
Group 1: (Blocks 8193-16384) [INODE_UNINIT, ITABLE_ZEROED]
  Checksum 0x132c, unused inodes 2048
  Backup superblock at 8193, Group descriptors at 8194-8194          #超级块的备份
  Reserved GDT blocks at 8195-8450
  Block bitmap at 260 (+4294959363), Inode bitmap at 276 (+4294959379)
  Inode table at 547-802 (+4294959650)
  844 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
  Free blocks: 11336, 11452-12288, 16379-16384
  Free inodes: 2049-4096
Group 2: (Blocks 16385-24576) [INODE_UNINIT, ITABLE_ZEROED]
  Checksum 0x6de3, unused inodes 2048
  Block bitmap at 261 (+4294951172), Inode bitmap at 277 (+4294951188)
  Inode table at 803-1058 (+4294951714)
  0 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
  Free blocks: 
  Free inodes: 4097-6144
Group 3: (Blocks 24577-32768) [INODE_UNINIT, ITABLE_ZEROED]
  Checksum 0xbade, unused inodes 2048
  Backup superblock at 24577, Group descriptors at 24578-24578        #超级块的备份
  Reserved GDT blocks at 24579-24834
  Block bitmap at 262 (+4294942981), Inode bitmap at 278 (+4294942997)
  Inode table at 1059-1314 (+4294943778)
  1789 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
  Free blocks: 24835-25101, 25103-26624
  Free inodes: 6145-8192
Group 4: (Blocks 32769-40960) [INODE_UNINIT, ITABLE_ZEROED]
  Checksum 0x3c6a, unused inodes 2048
  Block bitmap at 263 (+4294934790), Inode bitmap at 279 (+4294934806)
  Inode table at 1315-1570 (+4294935842)
  610 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
  Free blocks: 38303-38912
  Free inodes: 8193-10240
Group 5: (Blocks 40961-49152) [INODE_UNINIT, ITABLE_ZEROED]
  Checksum 0xadda, unused inodes 2048
  Backup superblock at 40961, Group descriptors at 40962-40962
  Reserved GDT blocks at 40963-41218
  Block bitmap at 264 (+4294926599), Inode bitmap at 280 (+4294926615)
  Inode table at 1571-1826 (+4294927906)
  1790 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
  Free blocks: 41219-43008
  Free inodes: 10241-12288

 

(2)GDT:Group Descriptor Table(块组描述符表)

  • 由很多块组描述符组成,整个分区分成多少个块组就对应有多少个块组描述符
  • 每个块组描述符(Group Descriptor)存储一个块组的描述信息,例如在这个块组中从哪里开始是inode表,从哪里开始是数据块,空闲的inode和数据块还有多少个等等
  • 和超级块类似,块组描述符表在每个块组的开头也都有一份拷贝,这些信息是非常重要的,一旦超级块意外损坏就会丢失整个分区的数据,一旦块组描述符意外损坏就会丢失整个块组的数据,因此它们都有多份拷贝

(3)bit map:位图

分为快位图(Block Bitmap)和结点位图(Inode Bitmap),机制如下:

【Block Bitmap】:当申请空闲块时,从位图上找出bit=0的字位,将其改为1,返回对应的块号;归还空闲块时,在位图上把该块所对应的字位改为0即可(如下图所示)。

 Linux运维实战之文件系统、链接文件_第3张图片

【Inode Bitmap】:和块位图类似,本身占一个块,其中每个bit表示一个inode是否空闲可用。

(4)Inode Table:Inode表:

  • 一个文件除了数据需要存储之外,一些描述信息也需要存储,例如文件类型(常规、目录、符号链接等),权限,文件大小,创建/修改/访问时间等,也就是"ls -l”命令看到的那些信息,这些信息存在inode中而不是数据块中。
  • 每个文件都有一个inode,一个块组中的所有inode组成了inode表
  • inode表占多少个块在格式化时就要决定并写入块组描述符中
  • mke2fs格式化工具的默认策略是一个块组有多少个8KB就分配多少个inode

(5)Data Blocks:数据块

  • 对于常规文件,文件的数据存储在数据块中
  • 对于目录,该目录下的所有文件名和目录名存储在数据块中,文件名保存在它所在目录的数据块中
  • 除文件名之外,ls -l命令看到的其它信息都保存在该文件的inode中
  • 目录也是一种文件,是一种特殊类型的文件
  • 对于符号链接,如果目标路径名较短则直接保存在inode中以便更快地查找,如果目标路径名较长则分配一个数据块来保存
  • 设备文件、FIFO和socket等特殊文件没有数据块,设备文件的主设备号和次设备号保存在inode中

6、ext文件系统中的目录:

从上面的Inode-table中可以看到,该表中存储的数据是文件的元数据(即描述文件属性的数据,例如文件类型、文件的时间戳、与文件权限相关的描述信息等),但并没有文件名,那文件名存储在什么地方呢?

文件名是保存在目录中的哈!下面重点说说目录。

文件系统要管理众多的文件,首要的问题是要把文件有条不紊地组织起来。每个文件都有目录项,目录是文件路径的映射(注意:目录并不是文件的容器),全部目录项组成目录文件,如下图所示:

Linux运维实战之文件系统、链接文件_第4张图片

可以看出,Linux系统的文件管理机构将文件属性从目录项分离出来了哈!分离出来的好处有两点:

(1)为文件的共享提供了方便:

若文件名不与文件属性信息分离,则指向同一个文件的多个目录项均应包含同一个文件的属性信息,也就是说,多个目录项中存有同一个文件属性信息的多个副本。这样显然造成存储空间的浪费哈!若文件属性分离,则指向同一个文件的多个目录项中只保存相同的Inode号,而文件属性信息只有一份,因此节省了存储空间。共享文件越多节省空间就越明显。增加共享链接或撤销共享链接也相当便利(后面我们会说到Linux系统中文件链接的知识哈)。

(2)减少文件“按名查找”引起的I/O传输:

假设外设为磁盘,每个磁盘块512字节。对Linux来说,若目录项含有文件属性,目录项占78个字节。若目录项不含有文件属性,目录项占16个字节。设某目录文件共有128个目录项,则前者共有约20个盘块,后者仅需4个盘块。由于每次启动I/O只传输一个盘块,所以后者查找一个目录项启动该盘的次数大大减少。

7、Linux系统树型目录组织结构:

再来考虑一个问题:Linux系统为什么要把目录组织成树状结构呢?

层次化结构能够大大减小查找的复杂度-->如果系统内文件很多,则目录文件会变得很长,要查找某个文件将耗费太多的时间(例如:我们要查找一个文件,但不知道它存储在什么地方,此时我们就需要从“/”下开始查找,那肯定是非常耗时间哈。若此时我们知道这个文件保存在"/var/log/” 下,那查找起来肯定快的多哈!)。树是一种层次化的数据结构,它由根结点,子结点以及子子结点组成。Linux借用树状结构来组织它的文件目录,形成树型目录组织。树型目录组织是多级目录组织的一种形式。Linux文件系统的目录组织结构如下图所示:

Linux运维实战之文件系统、链接文件_第5张图片

8、目录树上的搜索与操作:

(1)从目录的树根开始,经过各级子目录,最终到达数据文件名,才能对数据文件进行访问

(2)由根、各级目录名、数据文件名连接起来的字符串成为“绝对路径名”

(3)若用户当前正在某目录上进行操作,那么称其为“当前目录”

(4)给定路径名,从目录树上找到文件的Inode号的过程称为“文件名搜索”

Tips:为了加速文件查找,Linux通常采用缓存的机制(第一次查找文件时需要按顺序查找,之后就把结果缓存到buffer中)。 


二、Linux系统文件管理相关操作:

1、删除文件:

(1)将要删除的文件的Inode归类为空闲Inode

(2)将对应的磁盘块归为空闲块(不会对磁盘块做任何操作)

(3)完全删除文件(360文件粉碎机的原理):将要删除的文件所对应的磁盘块用0填充

结论:从上面可知:删除文件的速度会非常快。

2、复制文件:文件复制的过程是创建一个与原文件一模一样(Inode、磁盘块均相同)的文件

3、移动文件:

不同分区之间的文件移动:创建新文件(创建全新的Inode和磁盘块),删除老文件(把文件的Inode清空归类为空闲Inode,把对应的磁盘块归类为空闲块)

同一个分区里的文件移动: 创建一个新的Inode指向源文件的磁盘块;将源文件的Inode清空归类为空闲Inode。


三、ext文件系统的扩展属性:

lsattr:列出文件的扩展属性

Linux运维实战之文件系统、链接文件_第6张图片

chattr:(+/-/=)赋予相关扩展属性

    -i:真正只读

    -a:仅允许追加内容

    -c:自动压缩(类似于NTFS的压缩功能)

 Linux运维实战之文件系统、链接文件_第7张图片 


四、链接文件:

1、硬链接:指向同一个Inode的两个路径

【语法】

如何创建硬链接文件: ln SRC_FILE LINK_FILE

ls –l 命令的第二段显示出的数字指文件被硬链接的次数,举例如下:

Linux运维实战之文件系统、链接文件_第8张图片

【特性】

  • 不能跨分区使用;
  • 不能对目录创建硬链接(否则会产生循环引用);

例如目录A-->B,B-->C,C-->A,因此出现死循环。

  • 删除原文件路径,不影响链接文件的使用;
  • 所有文件指向同一个inode,因此,为它们是同一个文件;

【举例】

#----举例说明硬链接的特性----#

[root@Centos ~]# mkdir -pv LinkFileTest    #创建一个实验用目录
mkdir: created directory `LinkFileTest'
[root@Centos ~]# cd LinkFileTest/
[root@Centos LinkFileTest]# cp /etc/fstab .      #复制fstab文件到实验目录
[root@Centos LinkFileTest]# ln fstab fstab_bak       #为fstab文件创建硬链接
[root@Centos LinkFileTest]# ls -l
total 8
-rw-r--r--. 2 root root 924 Oct  8 20:45 fstab      
-rw-r--r--. 2 root root 924 Oct  8 20:45 fstab_bak        #可以看到两个文件的大小及其它相关属性都是一样的
[root@Centos LinkFileTest]# ls -i         #该命令可以查看文件的Inode号
396473 fstab  396473 fstab_bak         #可以看出原文件与其硬链接文件的Inode号完全一样

#尝试为目录创建硬链接:
[root@Centos LinkFileTest]# ln /tmp/ /hello
ln: `/tmp/': hard link not allowed for directory        #出错了哈:不允许为目录创建硬链接

 

2、软链接:(符号链接,symbolic link)

ls -l: 显示文件类型为l的文件

image            

【语法】

如何创建软链接文件: ln –s SRC_FILE LINK_FILE

特性

  • 不受分区限制;
  • 能够对目录创建;
  • 删除原文件,链接文件将无法使用;
  • 链接文件与原文件指向不同的inode,所以,并非同一个文件;
  • 软链接文件的大小为其所指向的文件的文件名称的字符数(只有Inode,没有具体的磁盘块)
  • 使用符号链接,查找文件的操作可能为两次
  • 软链接的文件类型取决于其所链接的文件

Tips:软连接类似于windows系统的快捷方式 

【举例】

#----举例说明软链接的特性----#

#能够对目录创建软链接
[root@Centos LinkFileTest]# ls -l
total 4
-rw-r--r--. 1 root root 924 Oct  8 21:06 fstab
lrwxrwxrwx. 1 root root   5 Oct  8 21:23 temp -> /tmp/

#链接文件与原文件指向不同的Inode
[root@Centos LinkFileTest]# ls -i fstab fstab_link 
396473 fstab  396478 fstab_link

#软连接文件的大小为其所指向的文件的文件名称的字符个数
[root@Centos LinkFileTest]# ls -l
total 4
-rw-r--r--. 1 root root 924 Oct  8 21:28 fstab
lrwxrwxrwx. 1 root root   5 Oct  8 21:25 fstab_link -> fstab      # fstab:正好5个字符哈
lrwxrwxrwx. 1 root root   5 Oct  8 21:23 temp -> /tmp/

#软连接的文件类型取决于原文件的类型
 [root@Centos LinkFileTest]# ls -l
total 4
-rw-r--r--. 1 root root 924 Oct  8 21:28 fstab
lrwxrwxrwx. 1 root root   5 Oct  8 21:25 fstab_link -> fstab      # fstab_link是普通文件
lrwxrwxrwx. 1 root root   5 Oct  8 21:23 temp -> /tmp/            #tmp是目录,可以cd进去
[root@Centos LinkFileTest]# cd temp/
[root@Centos temp]# ls
ssh-WnVOof5715  vmware-tools-distrib
[root@Centos temp]# ls /tmp/
ssh-WnVOof5715  vmware-tools-distrib                    #可以看到/tmp/与temp的内容相同

本次博客的内容就这么多哈,欢迎各位大大审阅、指正!~~