一、文件系统概述
1. 引导块
前文中介绍过磁盘需要进行分区和格式化,才能创建文件系统并使用,那么一块已经被各式化了分区其结构是什么样的呢?分区是按照柱面来划分的,而柱面包含的是磁道,磁道上包含的是扇区,一个分区上的前两个扇区(512 bytes * 2 = 1024 bytes)为引导块(Boot block),其作用为引导当前分区上的操作系统(与之相对的MBR是引导整个磁盘上的操作系统的,即指定启动哪一个分区上的操作系统),当然如果一块磁盘上只装了一个操作系统,那么Boot block并无太大意义,可能不被使用。除掉引导块,该分区剩余部分将被用来存放数据。
2. 索引
设想一下,如果一个目录下随意存放了10000个文件,而另一个目录下按照字母顺序,新建了10个目录,将10000个文件分别按字母放进不同的目录,并为其建立了索引,那么要找到具体某一个文件,必然是建立了索引的目录其检索速度更快。而索引的建立方式可以是多种多样的,比如按字母升序、字母降序、创建时间等等,不同的索引组织方式,就形成了不同的文件系统,但不论索引组织方式如何变化,其最终目的都是帮助用户实现按照文件名找到具体的文件。
针对不同的应用场景,文件系统的选择必然是不同的,比如有的文件系统需要让用户频繁的进行目录或文件的创建、删除、移动等操作,那么ext系列的文件系统是不错的选择;而有些服务器被当做数据库来使用,而数据库本身要不断的创建数据、更新数据、备份数据、扩展文件大小等等,其使用方式和普通用户的交互式使用是不同的,那么xfs这种文件系统会更加合适。至于如何选择合适的文件系统,需要根据实际生产环境来加以评估。
二、ext文件系统
1. 磁盘块
在文件系统中,索引通常位于磁盘块的首部,索引中存放了文件所在的条目信息。磁盘通过移动磁头、旋转盘片来定位到具体的扇区上,从而完成随机存取,而为了便于查找和管理,需要对扇区重新编号,按某种特定的逻辑结构进行排列,这个逻辑结构即为磁盘块。前文在介绍格式化时曾提到过为分区指定块大小,如1024 bytes, 2048bytes等,这个块大小指的就是磁盘块的大小。那么如果一个文件的大小为3k,而磁盘块大小为1024 bytes,那么就需要3个磁盘块来存放这个文件。这些磁盘块有自身的编号,所以要查找该文件的位置,只需要根据索引中记录的块编号,定位到具体的块上即可。索引中记录的这些条目信息(如文件对应的磁盘块指针、磁盘块二级指针、磁盘块三级指针、三个时间戳、大小、权限、属组属主等等,注意文件名不在此处存放),和文件本身的内容并无关系。因此,改变一个文件内容,实际是改变的磁盘块信息,而改变文件属性信息,是改变的文件的索引信息。
2. inode
索引中每一个文件的条目也自身的编号,这种编号称为inode(index node)号,故查找某一个文件,首先要找到该文件的inode号。
如果一个文件大小为3k,那么只需要3个1024 bytes的磁盘块来存放它;但如果一个文件有3G,那么就需要3 * 2^20个磁盘块来存放该文件,与之对应的,索引中的文件条目也需要保存这 3 * 2^20个磁盘块的信息,这将导致该条目无比巨大,这当然是不允许的。那么有没有方法能够压缩条目的大小呢?答案是一定的,我们可以采用层次化的方式来存放数据。比如将磁盘块所在的位置划分为一个个区域,如第1个区域有1000个磁盘块,第2个区域有3000个磁盘块,第3个区域有10000个区域......而将某一个区域作为一个整体来存放某一个文件,条目中建立具体的磁盘块指针(对应小文件,指向具体的磁盘块)、二级指针或三级指针(对应大文件,指向某一区域),这样就能大大减小索引条目的大小。当然建立二级指针或三级指针并不表示文件可以无限大,因为二级、三级指针也会受到索引条目大小的限制,故早期的ext2系列的文件系统,一个文件不能超过16 TB。
3.文件的路径映射
如果要查找某一个具体的文件,指定查找位置为/根目录,和指定/var/log目录,其查找范围截然不同,故查找效率也很不一样。因此目录实际上是一个文件的查找路径的映射。我们知道在Linux系统中,目录也是文件,既然是文件,那么它就会在索引中建立相应的条目,在具体的磁盘块上保存数据。前面提到过,索引中不保存文件名,其实文件名和相应的inode号都保存在目录中。
我们查看某个目录下的文件信息,会发现目录的大小要比普通文件的大小小很多,这是由于这个大小只是目录本身的大小,而非目录下的文件的大小。
比如要查找/var/log/messages这个文件,那么其查找过程如下:
①查找到/根目录(根目录是自查找文件),获取根目录中/var的文件名及对应的inode号,
根据/下查找到的inode号找到对应的索引中/var的inode号
②根据该条目找到具体保存/var文件信息的磁盘块,在该磁盘块上找到/var/log的文件名及其对应的inode号
③根据/var/log的inode号找到对应的索引中/var/log的条目,根据该条目找到具体保存/var/log文件信息的磁盘块
④在该磁盘块上找到/var/log/messages的文件名及其对应的inode号
⑤根据/var/log/messages的inode号找到对应的索引中/var/log/messages的条目
⑥根据该条目找到具体保存/var/log/messages文件信息的磁盘块
由此可以看出,一旦某个目录被删除了,那么目录中的文件就找不到了。
4. ext文件系统的扩展属性
之前使用ls -l 命令可以列出文件的详细信息,事实上,使用lsattr命令可以列出文件的扩展属性:
[root@localhost tutor]# lsattr
——————————————运行结果————————————————
1
2
3
4
5
6
7
8
9
10
11
|
-------------e- .
/memory1
.sh
# 这里某个属性如果没有启用,就使用“-”表示,启用了就显示相关属性
-------------e- .
/blank_line
.sh
-------------e- .
/if_cup
.sh
-------------e- .
/if_even_odd
.sh
-------------e- .
/if_cpu1
.sh
-------------e- .
/if_user3
.sh
-------------e- .
/3sum
.sh
-------------e- .
/version
.sh
-------------e- .
/abc
-------------e- .
/inittab
|
命令lsattr是用来显示属性信息的,此外还有一个chattr命令,可以用来修改属信息:
[root@localhost tutor]# man chattr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
——————————————运行结果————————————————
CHATTR(1) CHATTR(1)
NAME
chattr - change
file
attributes on a Linux
file
system
SYNOPSIS
chattr [ -RVf ] [ -
v
version ] [ mode ] files...
DESCRIPTION
chattr changes the
file
attributes on a Linux
file
system.
The
format
of a symbolic mode is +-=[acdeijstuADST].
# 这里可以增删的属性为中括号中所列举的内容: [acdeijstuADST],使用 + - 可以增删属性
The letters acdeijstuADST
select
the new attributes
for
the files: append only (a), compressed (c), no dump (d), extent
format
(e), immutable (i), data journalling (j), secure deletion (s), no
tail
-merging (t), undeletable (u), no atime updates (A), synchronous directory updates (D), synchronous updates (S), and
top
of directory hierarchy (T).
# 常用属性有:
# i:只读属性;
# a:只允许增添内容;
# A:任何时候访问文件都不会改变文件的访问时间戳
# c:保存文件时自动压缩文件
|
[root@localhost tutor]# chattr +i inittab
# 为inittab这个文件加上i属性
[root@localhost tutor]# lsattr
1
2
3
4
5
6
7
8
9
10
11
|
-------------e- .
/memory1
.sh
-------------e- .
/blank_line
.sh
-------------e- .
/if_cup
.sh
-------------e- .
/if_even_odd
.sh
-------------e- .
/if_cpu1
.sh
-------------e- .
/if_user3
.sh
-------------e- .
/3sum
.sh
-------------e- .
/version
.sh
-------------e- .
/abc
----i--------e- .
/inittab
# 可以看到 inittab文件已经具备i属性了
|
[root@localhost tutor]# vim inittab
# 编辑此文件,会发现inittab变成了只读文件,可见i属性为设置只读属性
[root@localhost tutor]# mv inittab inittab_1
1
2
|
mv
: cannot move `inittab
' to `inittab_1'
: Operation not permitted
# 有了i属性后,无法移动或修改文件名
|
[root@localhost tutor]# rm inittab
1
2
3
|
rm
: remove regular
file
`inittab'? y
rm
: cannot remove `inittab': Operation not permitted
# 也无法删除该文件
|
三、块组(block group)
上述过程描述的是文件查找的过程,那么文件创建过程又是怎样的呢?
首先需要在索引中创建一个inode号,然后在磁盘上创建一个或多个磁盘块以备数据的存储。现在的问题是如何确定哪一个inode和哪一个磁盘块是空闲的?可以扫描整个inode表和整个磁盘空间,但是可以想象这样做的效率是极其低下的。为了避免全表扫描,可以建立一个位图(bit map),让每一个inode对应一个位,每一个磁盘块对应一个位,这样只需要分别扫描inode位图和块位图,找出其中没有被占用的位,即可确定空闲的inode和磁盘块了。当然位图也需要占用相应的磁盘空间。
如果磁盘上存储了海量数目的文件,即使用了扫描位图的方式,其效率仍然比较低下,因此可以将磁盘块按照逻辑结构划分为块组(block group),如将100万个磁盘块划分为每5万个磁盘块一组,这样整个磁盘就划分成了20个块组,每一个组都自我管理,每次只扫描其中的一个块组,一个组的磁盘空间不够用,也可以跨组,通过这种方式可以大大提高效率。这些组的划分规则和管理方式也需要相应的磁盘空间来存储。
1. 超级块(Super Block)
这里每一个块组内的磁盘块个数是相同的,而每一个组都是自我管理的;但是 Block Group 0(块组0)比较独特,它的第2个1024个字节所在的块被称为超级块(Super Block),这个块是用来保存该磁盘上所有的块组的信息的,即每一个组从哪一个块开始,到哪一个块结束等信息。因此一旦超级块坏掉了,其他所有块组的信息都无法读取了,因此超级块需要有很多备份,存放于其他块组中,但使用只使用块组0中的超级块,一旦坏了就从其他块组中找一个加以恢复。
2. 全局描述表(Group Description Table)
紧跟在super block后面的是GDT,表示全局描述表,也称为块组描述表(Group Description Table),通常说到表,其中存放的多半是结构化信息,GDT也不例外,它存放的是块位图(Block Bitmap)和 inode位图(Inode Bitmap),即哪些块是已用的,哪些块是空闲的;哪些inode是已用的,哪些inode是空闲的,这样的位图比整个磁盘的位图要小得多,故扫描效率会提高很多。而通过Inode表(Inode Table)就可以找到相应的磁盘块(Data Blocks) 。
超级块(Super Block)并不是每个块组都有,但GDT每个块组都有
3. 查看超级块和块组信息的相关命令
使用tune2fs -l这个命令可以显示组信息,其中-l选项就是用来显示超级块信息的。
[root@localhost tutor]# tune2fs -l /dev/sdb3
——————————————运行结果————————————————
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
tune2fs 1.41.12 (17-May-2010)
Filesystem volume name: MYDAT
Last mounted on:
/mydata
Filesystem UUID: ead64b7a-80bd-4ad7-af3f-bece9a76e04c
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: (none)
Filesystem state: clean
Errors behavior: Continue
Filesystem OS
type
: Linux
Inode count: 655872
Block count: 10490412
Reserved block count: 200000
Free blocks: 10286628
Free inodes: 655860
First block: 1
Block size: 1024
Fragment size: 1024
Reserved GDT blocks: 256
# 块组描述表(Group Description Table)的相关信息
Blocks per group: 8192
Fragments per group: 8192
Inodes per group: 512
Inode blocks per group: 128
Flex block group size: 16
Filesystem created: Fri Jul 11 01:09:30 2014
Last
mount
time
: Fri Jul 11 13:35:43 2014
Last write
time
: Fri Jul 11 13:35:43 2014
Mount count: 6
Maximum
mount
count: 37
Last checked: Fri Jul 11 01:09:30 2014
Check interval: 15552000 (6 months)
Next check after: Wed Jan 7 00:09:30 2015
Lifetime writes: 193 MB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256
Required extra isize: 28
Desired extra isize: 28
Journal inode: 8
Default directory
hash
: half_md4
Directory Hash Seed: 7cfc9fb6-e210-4e90-9482-6dc66b1a3e26
Journal backup: inode blocks
|
可以使用dumpe2fs命令来查看超级块和块组的信息
[root@localhost tutor]# dumpe2fs /dev/sdb3 | less
——————————————运行结果————————————————
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
dumpe2fs 1.41.12 (17-May-2010)
Filesystem volume name: MYDAT
Last mounted on:
/mydata
Filesystem UUID: ead64b7a-80bd-4ad7-af3f-bece9a76e04c
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: (none)
Filesystem state: clean
Errors behavior: Continue
Filesystem OS
type
: Linux
Inode count: 655872
Block count: 10490412
Reserved block count: 200000
Free blocks: 10286628
Free inodes: 655860
First block: 1
Block size: 1024
Fragment size: 1024
Reserved GDT blocks: 256
Blocks per group: 8192
Fragments per group: 8192
Inodes per group: 512
Inode blocks per group: 128
Flex block group size: 16
Filesystem created: Fri Jul 11 01:09:30 2014
Last
mount
time
: Fri Jul 11 13:35:43 2014
Block size: 1024
Fragment size: 1024
Reserved GDT blocks: 256
Blocks per group: 8192
Fragments per group: 8192
Inodes per group: 512
Inode blocks per group: 128
Group 0: (Blocks 1-8192) [ITABLE_ZEROED]
Checksum 0xf3e0, unused inodes 500
Primary superblock at 1, Group descriptors at 2-42
# 超级块在第一个块组上
Reserved GDT blocks at 43-298
# 有保留GDT的组在第43到298个上
Block bitmap at 299 (+298), Inode bitmap at 315 (+314)
# 块位图在第299个块上,inode位图在315个块上
Inode table at 331-458 (+330)
# inode表在第331到458个块上
5800
free
blocks, 500
free
inodes, 2 directories, 500 unused inodes
# 一个有5800个块,500个空闲inode,已经使用了2个目录,还有500个空闲的inode
Free blocks: 2393-8192
# 空闲块为第2393到8192个
Free inodes: 13-512
# 空闲inode为13到512个
Group 2: (Blocks 16385-24576) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
# 没有超级块的备份
Checksum 0x1592, unused inodes 512
Block bitmap at 301 (+4294951212), Inode bitmap at 317 (+4294951228)
Inode table at 587-714 (+4294951498)
8192
free
blocks, 512
free
inodes, 0 directories, 512 unused inodes
Free blocks: 16385-24576
Free inodes: 1025-1536
Group 3: (Blocks 24577-32768) [INODE_UNINIT, ITABLE_ZEROED]
Checksum 0xfb42, unused inodes 512
Backup superblock at 24577, Group descriptors at 24578-24618
# 有超级块的备份,超级块的备份通常放在第3、5、7、9等块组上,一旦超级块坏了
# 可以复制备份进行恢复
Reserved GDT blocks at 24619-24874
Block bitmap at 302 (+4294943021), Inode bitmap at 318 (+4294943037)
Inode table at 715-842 (+4294943434)
7894
free
blocks, 512
free
inodes, 0 directories, 512 unused inodes
Free blocks: 24875-32768
Free inodes: 1537-2048
|
如果使用-h选项,可以只查看超级块信息
[root@localhost tutor]# dumpe2fs -h /dev/sdb3 |less
——————————————运行结果————————————————
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
dumpe2fs 1.41.12 (17-May-2010)
Filesystem volume name: MYDAT
Last mounted on:
/mydata
Filesystem UUID: ead64b7a-80bd-4ad7-af3f-bece9a76e04c
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: (none)
Filesystem state: clean
Errors behavior: Continue
Filesystem OS
type
: Linux
Inode count: 655872
Block count: 10490412
Reserved block count: 200000
Free blocks: 10286628
Free inodes: 655860
First block: 1
Block size: 1024
Fragment size: 1024
Reserved GDT blocks: 256
Blocks per group: 8192
Fragments per group: 8192
Fragments per group: 8192
Inodes per group: 512
Inode blocks per group: 128
Flex block group size: 16
Filesystem created: Fri Jul 11 01:09:30 2014
Last
mount
time
: Fri Jul 11 13:35:43 2014
Last write
time
: Fri Jul 11 13:35:43 2014
Mount count: 6
Maximum
mount
count: 37
Last checked: Fri Jul 11 01:09:30 2014
Check interval: 15552000 (6 months)
Next check after: Wed Jan 7 00:09:30 2015
Lifetime writes: 193 MB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256
Required extra isize: 28
Desired extra isize: 28
Journal inode: 8
Default directory
hash
: half_md4
Directory Hash Seed: 7cfc9fb6-e210-4e90-9482-6dc66b1a3e26
Journal backup: inode blocks
Journal features: (none)
Journal size: 32M
Journal length: 32768
Journal sequence: 0x00000007
Journal start: 0
|
使用du,表示disk usage,命令可以查看每个文件的大小,它也可以显示某一个目录下所有文件组合起来的大小。
[root@localhost tutor]# du /var/log
——————————————运行结果————————————————
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# 这里显示的是/var/log目录下每个文件的块大小
4
/var/log/ntpstats
4
/var/log/httpd
12
/var/log/ConsoleKit
4
/var/log/prelink
4
/var/log/samba/old
8
/var/log/samba
4
/var/log/cups
4
/var/log/ppp
692
/var/log/audit
156
/var/log/gdm
1460
/var/log/sa
4
/var/log/sssd
7100
/var/log
|
如果使用-s选项,表示summary,可以显示目录里所有文件的总大小,如果再加上-h选项,表示human readable,就能显示出人比较易读的方式:
[root@localhost tutor]# du -s /var/log
1
|
7100
/var/log
|
[root@localhost tutor]# du -sh /var/log
1
|
7.0M
/var/log
|
如果想查看/var目录下每一个子目录,包括其中文件的大小,可以使用如下方式:
[root@localhost tutor]# du -sh /var/*
——————————————运行结果————————————————
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
4.0K
/var/account
279M
/var/cache
4.0K
/var/crash
4.0K
/var/cvs
8.0K
/var/db
8.0K
/var/empty
4.0K
/var/games
4.0K
/var/gdm
77M
/var/lib
4.0K
/var/local
16K
/var/lock
7.0M
/var/log
0
/var/mail
4.0K
/var/nis
4.0K
/var/opt
4.0K
/var/preserve
356K
/var/run
120K
/var/spool
4.0K
/var/tmp
1.2M
/var/www
12K
/var/yp
|
使用df命令,表示disk free,可以用来显示磁盘空余空间量,其常用选项为-l,表示local,只显示本地文件系统,如果不加-l选项,可能会显示nfs的文件系统。注意,不论格式化的块大小是多少,该命令都显示为1k大小。
[root@localhost tutor]# df -l
——————————————运行结果————————————————
1
2
3
4
5
6
7
|
Filesystem 1K-blocks Used Available Use% Mounted on
# 文件系统 使用的单位 已用空间 可用空间 使用比例 挂载点
/dev/mapper/VolGroup-lv_root
23262376 4449116 17631564 21% /
tmpfs 510172 120 510052 1%
/dev/shm
/dev/sda1
495844 34840 435404 8%
/boot
/dev/sdb3
10323251 36623 10086628 1%
/mydata
/dev/sr0
288 288 0 100%
/media/20140715_2041
|
该命令同样也能使用-h选项,转换成人们易读的形式:
[root@localhost tutor]# df -lh
——————————————运行结果————————————————
1
2
3
4
5
6
|
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root
23G 4.3G 17G 21% /
tmpfs 499M 120K 499M 1%
/dev/shm
/dev/sda1
485M 35M 426M 8%
/boot
/dev/sdb3
9.9G 36M 9.7G 1%
/mydata
/dev/sr0
288K 288K 0 100%
/media/20140715_2041
|
使用-P选项,会显示成posix兼容的风格
[root@localhost tutor]# df -lP
——————————————运行结果————————————————
1
2
3
4
5
6
|
Filesystem 1024-blocks Used Available Capacity Mounted on
/dev/mapper/VolGroup-lv_root
23262376 4449116 17631564 21% /
tmpfs 510172 120 510052 1%
/dev/shm
/dev/sda1
495844 34840 435404 8%
/boot
/dev/sdb3
10323251 36623 10086628 1%
/mydata
/dev/sr0
288 288 0 100%
/media/20140715_2041
|
使用 -i 选项,则显示的是inode的使用信息而非块信息
[root@localhost tutor]# df -li
——————————————运行结果————————————————
1
2
3
4
5
6
|
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/VolGroup-lv_root
1479856 129332 1350524 9% /
tmpfs 127543 5 127538 1%
/dev/shm
/dev/sda1
128016 38 127978 1%
/boot
/dev/sdb3
655872 12 655860 1%
/mydata
/dev/sr0
0 0 0 -
/media/20140715_2041
|
如果该命令带上具体路径,则可以只显示单个文件系统的信息:
[root@localhost tutor]# df -l /dev/sdb3
1
2
|
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sdb3
10323251 36623 10086628 1%
/mydata
|