DomBro Studio

文件系统管理

2017/12/10

目录

1. Ext2文件系统

Linux 最传统的磁盘文件系统使用的是 EXT2 。所以要了解文件系统就得要由认识 EXT2 开始。

1.1 硬盘组成与分区

  • 整块磁盘的(物理)组成主要有

圆形的盘片(主要记录数据的部分);
机械手臂与机械手臂上的磁头(可读写盘片上的数据);

主轴马达,可以转动盘片,让机械手臂的磁头在盘片上读写数据。而数据存储与读取的重点在于盘片

  • 盘片上的物理组成

扇区(Sector)为最小的物理存储单位,每个扇区为512bytes;
将扇区组成一个圆,那就是柱面(Cylinder),柱面是分区(partition)的最小单位;
第一个扇区最重要,里面有硬盘主引导记录(Masterbootrecord,MBR)及分区表(partition table),其中MBR 占有446bytes,而partition table 则占有64bytes。
各种接口的磁盘在Linux中的文件名分别为:
/dev/sd[a-p][1-15]:为SCSI,SATA,USB,Flash等接口的磁盘文件名;
/dev/hd[a-d][1-63]:为IDE接口的磁盘文件名。

  • 磁盘的分区

主分区与扩展分区最多可以有4个(硬盘的限制);
扩展分区最多只能有一个(操作系统的限制);
逻辑分区是由扩展分区持续分出来的分区;
能够被格式化后作为数据访问的分区为主要分区与逻辑分区,扩展分区无法格式化;

所谓的磁盘分区指的是告诉操作系统“我这块磁盘在此分区可以访问的区域是由A柱面到B柱面之间的块”,如此一来操作系统就能够知道它可以在所指定的块内进行文件数据的读/写/查找等操作了。也就是说,磁盘分区意即指定分区的起始与结束柱面就可以

1.2 文件系统特性

操作系统的文件数据除了文件实际内容外,通常含有很多属性,例如Linux操作系统的文件权限(rwx)与文件属性(所有者、群组、时间参数等)。文件系统通常会将这两部分的数据分别存放在不同的块,权限与属性放置到inode 中,至于实际数据则放置到data block 块中。另外,还有一个超级块(superblock)会记录整个文件系统的整体信息,包括inode与block的总量、使用量、剩余量等。

  • 三个数据的简略意义

super block:记录此文件系统的整体信息,包括 inode/block 的总量、使用量、剩余量,以及文件系统的格式与相关信息等;
inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的block号码;
block:实际记录文件的内容,若文件太大时,会占用多个block。

inode—–>block号码——>文件实际数据 我们将这种数据访问的方法称为 索引式文件系统 EXT2就是索引式文件系统 如下图

图片1

1.3 Linux 的Ext2文件系统(inode)

inode 的内容用于记录文件的权限与相关属性,至于 block 块则是在记录文件的实际内容,而且文件系统一开始就将inode与block规划好了,除非重新格式化(或者利用resize2fs等命令更改文件系统大小),否则inode与block固定后就不再变动。但是,如果我的文件系统高达数百GB时,那么将所有的inode与block放置在一起将是很不明智的决定,因为inode与block的数量太大时,不容易管理。
因此 Ext2 文件系统在格式化的时候基本上是区分为多个块组(block group)的,每个块组都有独立的 inode/block/superblock 系统。感觉上就好像我们在当兵时,一个营里面有分成数个连,每个连有自己的联络系统,但最终都向营部回报连上最正确的信息一般。这样分成一群比较好管理。整个来说,Ext2格式化后如下图所示。

图片2

  • data block(数据块)

data block 是用来放置文件内容地方,在Ext2 文件系统中所支持的block 大小有1KB,2KB 及4KB三种而已。在格式化时block的大小就固定了,且每个block都有编号,以方便inode的记录。不过要注意的是,由于 block 大小的区别,会导致该文件系统能够支持的最大磁盘容量与最大单一文件容量并不相同

Block大小 1KB 2KB 4KB
最大单一文件限制 16GB 256GB 2TB
最大文件系统总量 2TB 8TB 16TB
  • Ext2 文件系统 block 限制

原则上,block的大小与数量在格式化完就不能够再改变了(除非重新格式化);
每个block内最多只能够放置一个文件的数据;
承上,如果文件大于block的大小,则一个文件会占用多个block数量
承上,若文件小于block,则该block的剩余空间就不能够再被使用了(磁盘空间会浪费)

  • 范例

假设你的Ext2文件系统使用4KB的block,而该文件系统中有10000个小文件,每个文件大小均为50bytes,请问此时你的磁盘浪费多少容量
答:Ext2 文件系统中一个 block 仅能容纳一个文件,因此每个 block 会浪费 4 × 1024 - 50 = 4046(bytes),整个系统会浪费 10000 × 4046 = 38.6 MB。然而所有文件大小仅为 10000 × 50(bytes) = 488.3KB 。

  • inodetable(inode表格)

如上所述,inode的内容主要记录文件的属性以及该文件实际数据是放置在哪几号block内!基本上,inode记录的文件数据至少有下面这些

该文件的访问模式(read/write/excute);
该文件的所有者与组(owner/group);
该文件的大小;
该文件创建或状态改变的时间(ctime);
最近一次的读取时间(atime);
最近修改的时间(mtime);
定义文件特性的标志(flag),如SetUID等该文件真正内容的指向(pointer)。

  • inode的数量与大小也是在格式化时就已经固定了,除此之外inode的特色

每个inode大小均固定为128bytes;

每个文件都仅会占用一个inode而已;
系统读取文件时需要先找到inode,并分析inode所记录的权限与用户是否符合,若符合才能够开始实际读取block的内容。

承上,因此文件系统能够创建的文件数量与inode的数量有关

  • inode/block 与文件大小关系

inode要记录的数据非常多,但偏偏又只有128bytes而已,而inode记录一个block号码要花掉4byte,假设我一个文件有400MB且每个block为4KB时,那么至少也要10万条block号码的记录。inode哪有这么多可记录的信息?为此我们的系统很聪明地将inode记录block号码的区域定义为12个直接、一个间接、一个双间接与一个三间接记录区。我们将inode的结构画一下好了,下图所示。
图中最左边为inode本身(128bytes),里面有12个直接指向block号码的对照,这12个记录就能够直接取得block号码。至于所谓的间接就是再拿一个block来当作记录block号码的记录区,如果文件太大时,就会使用间接会利用所谓的双间接,第一个block仅再指出下一个记录编号的block在哪里,实际记录的在第二个block当中。依此类推,三间接就是利用第三层block来记录编号。
这样子inode能够指定多少个block呢?我们以较小的1KB的block来说明好了,可以指定的情况如下:
12 个直接指向:12 × 1K=12K(可以提供的 block 的总大小
由于是直接指向,所以总共可记录12条记录。
间接:256 × 1K=256K (1K ÷ 4byte = 256个block号码记录,所以共可以提供 256K 的block)
每条block号码的记录会花去4bytes,因此1K的大小能够记录256条记录。
双间接:256 × 256 × 1K = 2 562K(1K ÷ 4byte = 记录的 256个block,其中每个block 又可以记录 256个block 共提供 2562K 的block)
第一层block会指定256个第二层,每个第二层可以指定256个号码
三间接:256 × 256 × 256 × 1K = 2 56 3 K
第一层block会指定256个第二层,每个第二层可以指定256个第三层,每个第三层可以指定256个号码。
总额:将直接、间接、双间接、三间接加总,得到12+256+256 × 256+256 × 256 × 256(K)=16GB

  • Superblock(超级块)

Superblock 是记录整个文件系统信息相关的地方,没有Surperblock,就没有这个文件系统了,他记录的主要信息有

block与inode的总量;
未使用与已使用的inode/block数量block 与inode 的大小(block 为1K,2K,4K,inode 为128 bytes);
文件系统的挂载时间、最近一次写入数据的时间、最近一次检验磁盘(fsck)的时间等文件系统的相关信息;
一个validbit 数值,若此文件系统已被挂载,则valid bit 为0,若未被挂载,则valid bit 为1。

 Superblock是非常重要的,因为我们这个文件系统的基本信息都写在这里,如果 superblock 死掉了,你的文件系统可能就需要花费很多时间去挽救。一般来说, superblock 的大小为 1 024bytes。
 此外,每个 block group 都可能含有 superblock。但是我们也说一个文件系统应该仅有一个superblock 而已,事实上除了第一个 block group 内会含有 superblock 之外,后续的 block group 不一定含有 superblock,而若含有 superblock 则该 superblock 主要是作为第一个 block group 内 superblock 的备份了,这样可以进行 superblock 的救援。

  • File system Description(文件系统描述)

这个区段可以描述每个 block group 的开始与结束的 block 号码,以及说明每个区段(superblock,bitmap,inodemap,data block)分别介于哪一个 block 号码之间。这部分也能够用dumpe2fs来查的。

  • block bitmap(block 对照表)

如果你想要添加文件时总会用到block。那你要使用哪个block来记录呢?当然是选择“空的block”来记录新文件的数据。那你怎么知道哪个 block 是空的?这就得要通过 block bitmap的辅助了。从 block bitmap 当中可以知道哪些 block 是空的,因此我们的系统就能够很快速地找到可使用的空间来处置文件。
同样,如果你删除某些文件时,那么那些文件原本占用的block号码就得要释放出来,此时在block bitmpap 当中相对应到该 block 号码的标志就得要修改成为“未使用中”。这就是 bitmap的功能。

  • inode bitmap(inode 对照表)

这个其实与 block bitmap 是类似的功能,只是 block bitmap 记录的是使用与未使用的 block号码,至于 inode bitmap 则是记录使用与未使用的 inode 号码。

  • dumpe2fs[-bh] 查询每个区段superblock的信息

[root@www ~]# dumpe2fs [-bh] 设备文件参数:
-b :列出保留为坏道的部分(一般用不到吧!)
-h :仅列出 superblock 的数据,不会列出其他的区段内容。

  • 范例 找出根目录磁盘文件名,并查看文件系统相关信息
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
[root@www ~]# df <==这个命令可以调出目前挂载的设备
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hdc2  9920624 3822848 5585708 41% /  <==就是这个
/dev/hdc3  4956316 141376 4559108 4% /home
/dev/hdc1  101086 11126 84741 12% /boot
tmpfs   371332  0 371332 0% /dev/sh
[root@www ~]# dumpe2fs /dev/hdc2
dumpe2fs 1.39(29-May-2006)
Filesystem volume name: /1   <==这个是文件系统的名称(Label)
Filesystem features: has_journal ext_attr resize_inode dir_index
filetype needs_recovery sparse_super large_file
Default mount options: user_xattr acl <==默认挂载的参数
Filesystem state:  clean   <==这个文件系统是没问题的(clean)
Errors behavior:  Continue
Filesystem OS type:  Linux
Inode count:   2560864  <==inode的总数
Block count:   2560359  <==block的总数
Free blocks:   1524760  <==还有多少个 block 可用
Free inodes:   2411225  <==还有多少个 inode 可用
First block:   0
Block size:   4096  <==每个 block 的大小
Filesystem created:  Fri Sep 5 01:49:20 2008
Last mount time:  Mon Sep 22 12:09:30 2008
Last write time:  Mon Sep 22 12:09:30 2008
Last checked:   Fri Sep 5 01Inode size:   128   <==每个 inode 的大小
Journal inode:   8   <==下面这三个与下一小节有关
Journal backup:  inode blocks
Journal size:   128M
Group 0:(Blocks 0-32767) <==第一个 data group 内容, 包含 block 的起始、结束号码
Primary superblock at 0, Group descriptors at 1-1 <==超级块在 0 号 block
Reserved GDT blocks at 2-626
Block bitmap at 627(+627), Inode bitmap at 628(+628)
Inode table at 629-1641(+629)     <==inode table 所在的 block
0 free blocks, 32405 free inodes, 2 directories <==所有 block 都用完了
Free blocks:
Free inodes: 12-32416      <==剩余未使用的 inode 号码
Group 1:(Blocks 32768-65535)
....(下面省略)....

1.4 与目录树的关系

 上面提到在 Linux 系统下,每个文件(不管是一般文件还是目录文件)都会占用一个 inode,且可依据文件内容大小来分配多个 block 给文件使用。而且我们知道目录的内容在记录文件名,一般文件才是实际记录数据内容的地方。下面来介绍目录与文件在 Ext2 文件系统当中是如何记录数据的。

  • 目录

当我们在 Linux 下的 ext2 文件系统新建一个目录时,ext2会分配一个inode与至少一块block给该目录。其中,inode记录该目录的相关权限与属性,并可记录分配到的那块block号码而block则是记录在这个目录下的文件名与该文件名占用的inode号码数据。也就是说目录所占用的block内容在记录如下的信息:

 如果想要实际查看 root 目录内的文件所占用的 inode 号码时,可以使用 ls-i 这个参数来处理:

1
2
3
4
5
[root@www ~]# ls -li
total 92
654683 -rw------- 1 root root 1474 Sep 4 18:27 anaconda-ks.cfg
648322 -rw-r--r-- 1 root root 42304 Sep 4 18:26 install.log
648323 -rw-r--r-- 1 root root 5661 Sep 4 18:25 install.log.syslogi9

 可以发现,使用ls -l /时,出现的目录几乎都是1024的倍数,因为每个block的大小都是1K,2K,4K。

1
2
3
4
5
6
7
[root@www ~]# ll -d / /bin /boot /proc /lost+found /sbin
drwxr-xr-x 23 root root 4096 Sep 22 12:09 /  <==一个 4K block
drwxr-xr-x 2 root root 4096 Sep 24 00:07 /bin  <==一个 4K block
drwxr-xr-x 4 root root 1024 Sep 4 18:06 /boot  <==一个 1K block
drwx------ 2 root root 16384 Sep 5 01:49 /lost+found <==4个 4K block
dr-xr-xr-x 96 root root 0 Sep 22 20:07 /proc  <==此目录不占硬盘空间
drwxr-xr-x 2 root root 12288 Sep 5 12:33 /sbin  <==3个 4K block

 目录并不只会占用一个 block 而已,即在目录下面的文件数如果太多而导致一个 block 无法容纳所有的文件名与 indoe 对照表时,Linux 会给予该目录一个 block 来继续记录相关的数据。

  • 文件

当我们在Linux下的ext2新建一个一般文件时,ext2会分配一个inode与相对于该文件大小的block数量给该文件。
例如:假设我的一个block为4KB,而我要新存储该文件。但同时请注意,由于inode仅有12个直接指向,因此还要多一个block来作为块号码的记录。

  • 目录树读取

inode 本身并不记录文件名,文件名的记录是在目录的block当中。因此在文件与目录的权限说明中,我们才会提到新增/删除/重命名文件名与目录的w权限有关的特点。那么因为文件名是记录在目录的block当中,因此当我们要读取某个文件时,就务必会经过目录的inode与block,然后才能够找到那个待读取文件的inode号码,最终才会读到正确的文件的block内的数据。

 由于目录树是由根目录开始读起,因此系统通过挂载的信息可以找到挂载点的 inode 号码(通常一个文件系统的最顶层inode号码会由2号开始),此时就能够得到根目录的inode内容,并依据该inode读取根目录的block内的文件名数据,再一层一层地往下读到正确的文件名。

  • 范例 当读取/etc/passwd 这个文件,系统如何读取
1
2
3
4
5
6
7
8
9
10
11
12
1./的inode
通过挂载点的信息找到/dev/hdc2的inode号码为2的根目录inode,且inode具有的权限让我们可以读取该block的内容(有r与x)。
2./的block
经过上个步骤取得block的号码,并找到该内容有etc/目录的inode号码。
3.etc/的inode
读取etc/的inode得知具有r与x的权限,因此可以读取etc/的block内容。
4.etc/的block
经过上个步骤取得block号码,并找到该内容有passwd文件的inode号码。
5.passwd的inode
读取passwd文件的inode得知具有r的权限,因此可以读取passwd的block内容。
6.passwd的block
最后将该block内容的数据读出来。

1.5 Ext2/Ext3 文件的访问与日志文件系统功能

  • 文件访问

上一节谈到了Ext2文件系统文件读取,新建一个文件或目录时,Ext2处理过程需要用到 blockmap 和 inodemap。假设想要新增一个文件,此时系统的行为是

1
2
3
4
1.先确定用户对于欲添加文件的目录是否具有w与x的权限,若有的话才能添加。
2.根据inode bitmap 找到没有使用的inode 号码,并将新文件的权限/属性写入。
3.根据block bitmap 找到没有使用中的block 号码,并将实际的数据写入block 中,且更新inode的block指向数据。
4.将刚才写入的inode 与block 数据同步更新inode bitmap 与block bitmap,并更新superblock的内容。

一般来说,我们将inode table与data block称为数据存放区域,至于其他例如super block、block bitmap与inode bitmap 等区段就被称为 metadata(中间数据),因为super block,inode bitmap及block bitmap的数据是经常变动的,每次添加、删除、编辑时都可能会影响到这三个部分的数据,因此才被称为中间数据的。

  • 日志文件系统功能

 数据不一致状态

在一般正常的情况下,上述的新增操作当然可以顺利完成。但是如果有个万一怎么办?例如你的文件在写入文件系统时,因为不明原因导致系统中断(例如突然停电、系统内核发生错误等的怪事发生时),所以写入的数据仅有 inode table 及 data block 而已,最后一个同步更新中间数据的步骤并没有做完,此时就会发生 meta dat的内容与实际数据存放区产生不一致的情况了。

 日志文件系统(Journaling file system)

为了避免上述提到的文件系统不一致的情况发生,因此我们的前辈们想到一个方式,如果在我们的文件系统当中规划出一个块,该块专门记录写入或修订文件时的步骤,那不就可以简化一致性检查的步骤了?也就是说:
1.预备:当系统要写入一个文件时,会先在日志记录块中记录某个文件准备要写入的信息。
2.实际写入:开始写入文件的权限与数据;开始更新meta data 的数据。
3.结束:完成数据与meta data 的更新后,在日志记录块当中完成该文件的记录在这样的程序当中,万一数据的记录过程当中发生了问题,那么我们的系统只要去检查日志记录块就可以知道哪个文件发生了问题,针对该问题来做一致性的检查即可,而不必针对整块文件系统去检查,这样就可以达到快速修复文件系统的能力了。这就是日志式文件最基础的功能。

1.6 Linux 文件系统操作

  • Linux 文件系统操作

所有的数据都得要加载到内存后CPU才能够对该数据进行处理。如果你经常编辑一个很大的文件,在编辑的过程中又频繁地要系统来写入磁盘中,由于磁盘写入的速度要比内存慢很多,因此你会经常耗在等待硬盘的写入/读取上。真没效率。
为了解决这个效率的问题,因此我们的Linux使用的方式是通过一个称为异步处理(asynchronously)的方式。所谓的异步处理是这样的:
当系统加载一个文件到内存后,如果该文件没有被改动过,则在内存区段的文件数据会被设置为(clean)的。但如果内存中的文件数据被更改过了(例如你用nano去编辑过这个文件),此时该内存中的数据会被设置为Dirty。此时所有的操作都还在内存中执行,并没有写入到磁盘中。系统会不定时地将内存中设置为 Dirty 的数据写回磁盘,以保持磁盘与内存数据的一致性。你也可以利用第 5 章谈到的sync命令来手动强迫写入磁盘。
我们知道内存的速度要比硬盘快得多,因此如果能够将常用的文系统会将常用的文件数据放置到主存储器的缓冲区,以加速文件系统的读/写。
承上,因此Linux的物理内存最后都会被用光。这是正常的情况,可加速系统性能。
你可以手动使用sync来强迫内存中设置为Dirty的文件回写到磁盘中
若正常关机时,关机命令会主动调用sync来将内存的数据回写入磁盘内。
但若不正常关机(如断电、死机或其他不明原因),由于数据尚未回写到磁盘内,因此重新启动后可能会花很多时间在进行磁盘检验,甚至可能导致文件系统的损毁(非磁盘损坏)。

1.7 挂载点(mount point)的意义

每个文件系统都有独立的 inode、block、super block 等信息,这个文件系统要能够链接到目录树才能被我们使用。将文件系统与目录树结合的操作我们称为挂载。重点是:挂载点一定是目录,该目录为进入该文件系统的入口。因此并不是你有任何文件系统都能使用,必须要“挂载”到目录树的某个目录后,才能够使用该文件系统的。

  • 范例
1
2
3
4
5
6
7
[root@www ~]# ls -lid / /boot /home
2 drwxr-xr-x 23 root root 4096 Sep 22 12:09 /
2 drwxr-xr-x 4 root root 1024 Sep 4 18:06 /boot
2 drwxr-xr-x 6 root root 4096 Sep 29 02:21 /home
由于文件系统最顶层的目录的inode一般为2号,因此可以发现/,/boot,/home为三个不同的文件系统。(因为每一行的文件属性并不相同,
且三个目录的挂载点也均不相同之故。)
如果从使用文件系统的观点来看,同一个文件系统的某个inode只会对应到一个文件内容而已(因为一个文件占用一个inode的原因)

2. 文件系统的简单操作

2.1 磁盘与目录的容量:df,du

  • df: 列出文件系统的整体磁盘使用量
1
2
3
4
5
6
7
8
[root@www ~]# df [-ahikHTm] [目录或文件名参数:
-a :列出所有的文件系统,包括系统特有的 /proc 等文件系统;
-k :以 KB的容量显示各文件系统;
-m :以 MB的容量显示各文件系统;
-h :以人们较易阅读的 GB、 MB、 KB等格式自行显示;
-H :以 M=1000K 替代 M=1024K 的进位方式;
-T :连同该分区的文件系统名称(例如 ext3) 也列出;
-i :不用硬盘容量,而以 inode 的数量来显示。
  • 范例:df 将系统内所有的文件系统列出来(不同系统会有不同显示)
1
2
3
4
5
6
7
8
[root@www ~]# df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hdc2  9920624 3823112 5585444 41% /
/dev/hdc3  4956316 141376 4559108 4% /home
/dev/hdc1  101086 11126 84741 12% /boot
tmpfs   371332  0 371332 0% /dev/shm
# 在 Linux 下面如果 df 没有加任何参数,那么默认会将系统内所有的被挂载的文件系统(不含特殊内存内的文件系统与 swap) 都以 1 KB 的容量来列出来。
# 至于那个 /dev/shm 是与内存有关的挂载。
  • df范例 : 将容量以已读的容量格式显示出来
1
2
3
4
5
6
7
[root@www ~]# df -h
Filesystem   Size Used Avail Use% Mounted on
/dev/hdc2   9.5G 3.7G 5.4G 41% /
/dev/hdc3   4.8G 139M 4.4G 4% /home
/dev/hdc1   99M 11M 83M 12% /boot
tmpfs    363M 0 363M 0% /dev/shm
# 不同上一范例,这里会以 G、M 等容量格式显示出来,比较容易看。
  • df范例:将系统内的所有特殊文件格式及名称都列出来
1
2
3
4
5
6
7
8
9
10
11
12
[root@www ~]# df -aT
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/hdc2 ext3 9920624 3823112 5585444 41% proc  proc  0  0  0 - /proc
sysfs  sysfs  0  0  0 - /sys
devpts devpts  0  0  0 - /dev/pts
/dev/hdc3 ext3 4956316 141376 4559108 4% /home
/dev/hdc1 ext3 101086 11126 84741 12% /boot
tmpfs  tmpfs 371332  0 371332 0% /dev/shm
none binfmt_misc  0  0  0 - /proc/sys/fs/binfmt_misc
sunrpc rpc_pipefs  0  0  0 - /var/lib/nfs/rpc_pipefs
# 系统里面其实还有很多特殊的文件系统存在的。那些比较特殊的文件系统几乎都是在内存当中,例如 /proc 这个挂载点。
因此,这些特殊的文件系# 都不会占据硬盘空间。
  • df范例:将 /etc 下面的可用的磁盘容量以易读的容量格式显示
1
2
3
4
5
[root@www ~]# df -h /etc
Filesystem   Size Used Avail Use% Mounted on
/dev/hdc2    9.5G 3.7G 5.4G 41% /
# 这个范例比较有趣一点,在 df 后面加上目录或者是文件时,df 会自动分析该目录或文件所在的分区,并将该分区的容量显示出来,
# 所以,你就可以知道某个目录下面还有多少容量可以使用了。
  • df范例:将目前各个分区当中可用的 inode 数量列出
1
2
3
4
5
6
7
8
[root@www ~]# df -ih
Filesystem   Inodes IUsed IFree IUse% Mounted on
/dev/hdc2   2.5M  147K  2.3M  6% /
/dev/hdc3   1.3M  46  1.3M  1% /home
/dev/hdc1   26K  34  26K  1% /boot
tmpfs     91K   1  91K 1% /dev/shm
# 这个范例则主要列出可用的 inode 剩余量与总容量。
# 你可以清楚地发现到,通常 inode 的数量剩余都比 block 还要多呢!
  • 范例输出的信息说明
1
2
3
4
5
Filesystem:代表该文件系统是在哪个分区,所以列出设备名称。
1k-blocks:说明下面的数字单位是1KB。可利用-h或-m来改变容量Used:顾名思义,就是使用掉的硬盘空间啦!
Available:也就是剩下的磁盘空间大小。
Use%:就是磁盘的使用率。如果使用率高达 90%以上时,最好需要注意一下了,免得容量不足造成系统问题。(例如最容易被填满的/var/spool/mail这个放置邮件的磁盘)。
Mountedon:就是磁盘挂载的目录所在(挂载点)。
  • 注意

 另外需要注意的是,如果使用-a 这个参数时,系统会出现/proc 这个挂载点,但是里面的东西都是0,不要张。/proc的东西都是Linux系统所需要加载的系统数据,而且是挂载在内存当中的,所以当然没有占任何的硬盘空间。
 至于那个/dev/shm/目录,其实是利用内存虚拟出来的磁盘空间。由于是通过内存虚拟出来的磁盘,因此你在这个目录下面新建任何数据文件时,访问速度是非常快速的(在内存内工作)。不过,也由于它是内存虚拟出来的,因此这个文件系统的大小在每部主机上都不一样,而且新建的东西在下次开机时就消失了,因为是在内存中。

  • du 查看文件和目录磁盘使用空间
1
2
3
4
5
6
7
[root@www ~]# du [-ahskm] 文件或目录名称
选项与参数:
-a :列出所有的文件与目录容量,因为默认仅统计目录下面的文件量而已;
-h :以人们较易读的容量格式(G/M) 显示;
-s :列出总量而已,而不列出每个各别的目录占用
-k :以 KB列出容量显示;
-m :以 MB列出容量显示。
  • du 范例: 列出目前目录下得所有文件容量
1
2
3
4
5
6
7
8
9
[root@www ~]# du
8  ./test4 <==每个目录都会列出来
8  ./test2
....中间省略....
12 ./.gconfd <==包括隐藏文件的目录
220 .  <==这个目录(.)所占用的总量
# 直接输入 du 没有加任何参数时,则 du 会分析目前所在目录的文件与目录所占用的硬盘空间。但是,实际显示时,仅会显示目录容量(不含文件),
# 因此 . 目录有很多文件没有被列出来,所以全部的目录相加不会等于 . 的容量。
# 此外,输出的数值数据为 1K 大小的容量单位。
  • du 范例:将文件的容量也列出来
1
2
3
4
5
6
[root@www ~]# du -a
12 ./install.log.syslog <==有文件的列表了
8  ./.bash_logout
8  ./test4
8  ./test212 ./.gconfd
220 .
  • du 范例:检查根目录下每个目录所占用的容量
1
2
3
4
5
6
7
8
9
10
11
[root@www ~]# du -sm /*
7  /bin
6  /boot
.....中间省略....
0  /proc
.....中间省略....3859 /usr <==系统初期最大就是它了。
77 /var
# 这是个很常被使用的功能:利用通配符 * 来代表每个目录,
# 如果想要检查某个目录下那个子目录占用最大的容量,可以用这个方法找出来
# 值得注意的是,如果刚才安装好 Linux 时,那么整个系统容量最大的应该是 /usr
# 而 /proc 虽然有列出容量,但是那个容量是在内存中,不占硬盘空间。

与 df 不一样的是,du 这个命令其实会直接到文件系统内去查所有的文件数据

2.2 连接文件:ln

 Linux 下面连接文件有两种,一种是类似 Windows 的快捷方式功能文件,可以快速连接到目标文件;另一种是通过文件系统的 inode 连接来产生新文件名,而不是产生新文件,这种成为硬链接(hard link)。这两个完全是不一样的东西。

  • hard link(硬连接或实际连接)

前面提到,文件名只与目录有关,但文件内容与 inode 有关。那么想一想,有没有可能有多个文件名对应到同一个inode 号码呢?那就是 hard link 的由来。
所以简单地说:hardlink只是在某个目录下新建一条文件名连接到某inode号码的关联记录而已。

  • 举个例子:

假设系统有个/root/crontab它是/etc/crontab的实际连接,也就是说这两个文件名连接到同一个inode,自然这两个文件名的所有相关信息都会一模一样(除了文件名之外)。实际的情况可以如下所示:

1
2
3
4
[root@www ~]# ln /etc/crontab . <==创建实际连接的命令
[root@www ~]# ll -i /etc/crontab /root/crontab
1912701 -rw-r--r-- 2 root root 255 Jan 6 2007 /etc/crontab
1912701 -rw-r--r-- 2 root root 255 Jan 6 2007 /root/crontab

你可以发现两个文件名都连接到1912701这个inode号码,是否文件的权限、属性完全一样呢?因为这两个“文件名”其实是一模一样的“文件”,而且你也会发现第二个字段由原本的1 变成2 了!那个字段称为“连接”,这个字段的意义为“有多少个文件名连接到这个inode号码”的意思,如下图

上图的意思是,你可以通过1或2的目录inode指定的block找到两个不同的文件名,而不管使用哪个文件名均可以指到real那个inode去读取到最终数据。那这样有什么好处呢?最大的好处就是“安全”。如图所示,如果你将任何一个“文件名”删除,其实inode与block都还是存在的。此时你可以通过另一个“文件名”来读取到正确的文件数据。此外,不论你使用哪个“文件名”来编辑,最终的结果都会写入到相同的inode与block中,因此均能进行数据的修改。

由此可以知道,使用 hard link 设置连接文件时,磁盘空间与 inode 的数目都不会改变。 hard link 只是在某个目录下的 block 多写入一个关联数据而已,既不会增加 inode 也不会耗用 block 数量。

  • hard link 限制

不能跨文件系统;
不能连接到目录。
不能跨文件系统还好理解,那不能硬连接到目录又是怎么回事呢?这是因为如果使用hard link连接到目录时,连接的数据需要连同被连接目录下面的所有数据都建立连接,举例来说,如果你要将/etc 使用硬连接创建一个/etc_hd 的目录时,那么在/etc_hd 下面的所有文件名同时都与/etc下面的文件名要创建硬连接的,而不是仅连接到/etc_hd与/etc而已。并且,未来如果需要在/etc_hd 下面创建新文件时,连带的,/etc 下面的数据又得要创建一次 hard link,因此造成环境相当大的复杂度。目前 hard link 对于目录暂时还是不支持的。

  • symbolic link(符号连接,也即是快捷方式)

相比于 hard link symbolic link 就好理解多了。基本上,symbolic link 就是在创建一个独立的文件,而这这个文件会让数据的读取指向它连接的那个文件的文件名。由于只是利用文件来作为指向操作,所以,当源文件被删除之后,symbolic link 的文件会“开不了”,会一直说“无法打开某文件”。实际上就是找不到源文件“文件名”而已。

  • 举个例子:我们先创建一个符号连接文件连接到/etc/crontab去看看:
1
2
3
4
[root@www ~]# ln -s /etc/crontab crontab2
[root@www ~]# ll -i /etc/crontab /root/crontab2
1912701 -rw-r--r-- 2 root root 255 Jan 6 2007 /etc/crontab
654687 lrwxrwxrwx 1 root root 12 Oct 22 13:58 /root/crontab2 -> /etc/crontab

由上面的结果我们可以知道两个文件指向不同的inode号码,当然就是两个独立的文件存在。而且连接文件的重要内容就是它会写上目标文件的“文件名”,你可以发现为什么上面连接文件的大小为12bytes呢?因为箭头(->)右边的文件名“/etc/crontab”总共有12个英文,每个英文占用1个byte,所以文件大小就是12bytes了!如下图

由1 号inode 读取到连接文件的内容仅有文件名,根据文件名连接到正确的目录去取得目标文件的 inode ,最终就能够读取到正确的数据了。你可以发现的是,如果目标文件(/etc/crontab)被删除了,那么整个环节就会无法继续进行下去,所以就会发生无法通过连接文件读取的问题了。

  • ln 命令
1
2
3
4
[root@www ~]# ln [-sf] 源文件 目标文件
参数:
-s :如果不加任何参数就进行连接,那就是hard link,至于 -s 就是symbolic link
-f :如果目标文件存在时,就主动将目标文件直接删除后再创建。
  • ln 范例
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
范例一:将 /etc/passwd 复制到 /tmp 下面,并且查看 inode 与 block
[root@www ~]# cd /tmp
[root@www tmp]# cp -a /etc/passwd .
[root@www tmp]# du -sb ; df -i .Filesystem   Inodes IUsed IFree IUse% Mounted on
/dev/hdc2   2560864 149738 2411126 6% /
# 利用 du 与 df 来检查一下目前的参数,那个 du -sb
# 是计算整个 /tmp 下面有多少 bytes 的啦!

范例二:将 /tmp/passwd 制作 hard link 成为 passwd-hd 文件,并查看文件与容量
[root@www tmp]# ln passwd passwd-hd
[root@www tmp]# du -sb ; df -i .
18340 .
Filesystem   Inodes IUsed IFree IUse% Mounted on
/dev/hdc2   2560864 149738 2411126 6% /
#即使多了一个文件在 /tmp 下面,整个 inode 与 block 的容量并没有改变。
[root@www tmp]# ls -il passwd*
586361 -rw-r--r-- 2 root root 1945 Sep 29 02:21 passwd
586361 -rw-r--r-- 2 root root 1945 Sep 29 02:21 passwd-hd
# 原来是指向同一个 inode ,另外,那个第二列的连接数也会增加!

范例三:将 /tmp/passwd 创建一个符号连接
[root@www tmp]# ln -s passwd passwd-so
[root@www tmp]# ls -li passwd*
586361 -rw-r--r-- 2 root root 1945 Sep 29 02:21 passwd
586401 lrwxrwxrwx 1 root root 6 Oct 22 14:18 passwd-so -> passwd
# passwd-so 指向的 inode number 不同了。这是一个新的文件,这个文件的内容是指向
# passwd 的。passwd-so 的大小是 6bytes ,因为 passwd 共有6个字符之故
[root@www tmp]# du -sb ; df -i .
18346 .
Filesystem   Inodes IUsed IFree IUse% Mounted on
/dev/hdc2   2560864 149739 2411125 6% /
#整个容量与 inode 使用数都改变了。

范例四:删除源文件 passwd ,其他两个文件是否能够开启?
[root@www tmp]# rm passwd[root@www tmp]# cat passwd-hd
......正常显示完毕!
[root@www tmp]# cat passwd-so
cat: passwd-so: No such file or directory
[root@www tmp]# ll passwd*
-rw-r--r-- 1 root root 1945 Sep 29 02:21 passwd-hd
lrwxrwxrwx 1 root root 6 Oct 22 14:18 passwd-so -> passwd
#符号连接果然无法打开。另外,如果符号链接的目标文件不存在,
# 其实文件名的部分就会有特殊的颜色显示。

使用ln 如果不加任何参数的话,那么就是 hard link。如同范例二的情况,增加了 hard link 之后,可以发现使用ls-l时,显示的link那一列属性增加。而如果这个时候删掉passwd会发生什么事情呢?passwd -hd 的内容还是会跟原来 passwd 相同,但是 passwd-so 就会找不到该文件。

  • 关于目录的连接数量

当我们新建一个空目录时,新的目录连接数为2 (. 和 ..) 而上层目录连接数增加 1。

说明

整理笔记参考了 《鸟哥的Linux私房菜》 一书。这本书我是买的京东阅读的正版电子书籍。

如果不想买书看的话可以直接戳这里进入鸟哥Linux私房菜的线上博客 : http://linux.vbird.org/。请大家支持正版!!

CATALOG
  1. 1. 目录
  2. 2. 1. Ext2文件系统
    1. 2.1. 1.1 硬盘组成与分区
    2. 2.2. 1.2 文件系统特性
    3. 2.3. 1.3 Linux 的Ext2文件系统(inode)
    4. 2.4. 1.4 与目录树的关系
    5. 2.5. 1.5 Ext2/Ext3 文件的访问与日志文件系统功能
    6. 2.6. 1.6 Linux 文件系统操作
    7. 2.7. 1.7 挂载点(mount point)的意义
  3. 3. 2. 文件系统的简单操作
    1. 3.1. 2.1 磁盘与目录的容量:df,du
    2. 3.2. 2.2 连接文件:ln
    3. 3.3. 说明