一、文件系统概述
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
——————————————运行结果————————————————
-------------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
——————————————运行结果———————————————— 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
-------------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
mv: cannot move `inittab' to `inittab_1': Operation not permitted # 有了i属性后,无法移动或修改文件名
[root@localhost tutor]# rm inittab
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
——————————————运行结果————————————————
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
——————————————运行结果————————————————
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
——————————————运行结果————————————————
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
——————————————运行结果————————————————
# 这里显示的是/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
7100 /var/log
[root@localhost tutor]# du -sh /var/log
7.0M /var/log
如果想查看/var目录下每一个子目录,包括其中文件的大小,可以使用如下方式:
[root@localhost tutor]# du -sh /var/*
——————————————运行结果————————————————
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
——————————————运行结果————————————————
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
——————————————运行结果————————————————
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
——————————————运行结果————————————————
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
——————————————运行结果————————————————
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
Filesystem 1K-blocks Used Available Use% Mounted on /dev/sdb3 10323251 36623 10086628 1% /mydata