第八章、Linux 磁盘与文件系统管理

1. 认识 EXT2 文件系统
  1.1 硬盘组成与分割的复习
  1.2 文件系统特性: 索引式文件系统
  1.3 Linux 的 EXT2 文件系统(inode): data block, inode table, superblock, dumpe2fs
  1.4 与目录树的关系
  1.5 EXT2/EXT3 文件的存取与日志式文件系统的功能
  1.6 Linux 文件系统的运行
  1.7 挂载点的意义 (mount point)
  1.8 其他 Linux 支持的文件系统与 VFS
2. 文件系统的简单操作
  2.1 磁盘与目录的容量: df, du
  2.2 实体链接与符号链接: ln
3. 磁盘的分割、格式化、检验与挂载
  3.1 磁盘分区: fdisk, partprobe
  3.2 磁盘格式化: mkfs, mke2fs
  3.3 磁盘检验: fsck, badblocks
  3.4 磁盘挂载与卸除: mount, umount
  3.5 磁盘参数修订: mknod, e2label, tune2fs, hdparm
4. 配置启动挂载:
  4.1 启动挂载 /etc/fstab 及 /etc/mtab
  4.2 特殊装置 loop 挂载(映象档不刻录就挂载使用)
5. 内存置换空间(swap)之建置:
  5.1 使用实体分割槽建置swap
  5.2 使用文件建置swap
  5.3 swap使用上的限制
6. 文件系统的特殊观察与操作
  6.1 boot sector 与 superblock 的关系
  6.2 磁盘空间之浪费问题
  6.3 利用 GNU 的 parted 进行分割行为
7. 重点回顾
8. 本章习题
9. 参考数据与延伸阅读
10. 针对本文的建议:http://phorum.vbird.org/viewtopic.php?t=23881 
  1. 认识 EXT2 文件系统

1.1 硬盘组成与分割的复习

首先说明一下磁盘的物理组成,整颗磁盘的组成主要有:
圆形的磁盘盘(主要记录数据的部分);
机械手臂,与在机械手臂上的磁盘读取头(可擦写磁盘盘上的数据);
主轴马达,可以转动磁盘盘,让机械手臂的读取头在磁盘盘上读写数据。

而磁盘盘上的物理组成则为(假设此磁盘为单盘片, 磁盘盘图标请参考第三章图2.2.1的示意):
扇区(Sector)为最小的物理储存单位,每个扇区为 512 bytes;
将扇区组成一个圆,那就是磁柱(Cylinder),磁柱是分割槽(partition)的最小单位;
第一个扇区最重要,里面有:(1)主要启动区(Master boot record, MBR)及分割表(partition table), 其中 MBR 占有 446 bytes,而 partition table 则占有 64 bytes。

各种接口的磁盘在Linux中的文件名分别为:
/dev/sd[a-p][1-15]:为SCSI, SATA, U盘, Flash闪盘等接口的磁盘文件名;
/dev/hd[a-d][1-63]:为 IDE 接口的磁盘文件名;

所谓的磁盘分区指的是告诉操作系统『我这颗磁盘在此分割槽可以存取的区域是由 A 磁柱到 B 磁柱之间的区块

指定分割槽的磁柱范围是记录在哪里?就是第一个扇区的分割表中啦!但是因为分割表仅有64bytes而已
1、主要分割与扩展分配最多可以有四笔(硬盘的限制)
2、扩展分配最多只能有一个(操作系统的限制)
3、逻辑分割是由扩展分配持续切割出来的分割槽;
4、能够被格式化后,作为数据存取的分割槽为主要分割与逻辑分割。扩展分配无法格式化;
逻辑分割的数量依操作系统而不同,在Linux系统中,IDE硬盘最多有59个逻辑分割(5号到63号), SATA硬盘则有11个逻辑分割(5号到15号)。

1.2 文件系统特性: 索引式文件系统

传统的磁盘与文件系统之应用中,一个分割槽就是只能够被格式化成为一个文件系统,所以我们可以说一个 filesystem 就是一个 partition。但是由于新技术的利用,例如我们常听到的LVM与软件磁盘阵列(software raid), 这些技术可以将一个分割槽格式化为多个文件系统(例如LVM),也能够将多个分割槽合成一个文件系统(LVM, RAID)! 所以说,目前我们在格式化时已经不再说成针对 partition 来格式化了, 通常我们可以称呼一个可被挂载的数据为一个文件系统而不是一个分割槽喔!

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

每个 inode 与 block 都有编号,至于这三个数据的意义可以简略说明如下:

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

这种数据存取的方法我们称为索引式文件系统(indexed allocation)。
索引式文件系统

其他的惯用文件系统可以比较一下啊? 有的,那就是我们惯用的闪盘(闪存),闪盘使用的文件系统一般为 FAT 格式。
FAT 这种格式的文件系统并没有 inode 存在,所以 FAT 没有办法将这个文件的所有 block 在一开始就读取出来。每个 block 号码都记录在前一个 block 当中。
FAT格式文件系统

所谓的『碎片整理』, 需要碎片整理的原因就是文件写入的 block 太过于离散了,此时文件读取的效能将会变的很差所致。 这个时候可以透过碎片整理将同一个文件所属的 blocks 汇整在一起,这样数据的读取会比较容易啊! 想当然尔,FAT 的文件系统需要经常的碎片整理一下,那么 Ext2 是否需要磁盘重整呢?基本上不是太需要。

1.3 Linux 的 EXT2 文件系统(inode): data block, inode table, superblock, dumpe2fs

文件系统一开始就将 inode 与 block 规划好了,除非重新格式化(或者利用 resize2fs 等命令变更文件系统大小),否则 inode 与 block 固定后就不再变动。但是如果仔细考虑一下,如果我的文件系统高达数百GB时, 那么将所有的 inode 与 block 通通放置在一起将是很不智的决定,因为 inode 与 block 的数量太庞大,不容易管理。
因此 Ext2 文件系统在格式化的时候基本上是区分为多个区块群组 (block group) 的,每个区块群组都有独立的 inode/block/superblock 系统。
区块群组

在整体的规划当中,文件系统最前面有一个启动扇区(boot sector),这个启动扇区可以安装启动管理程序, 这是个非常重要的设计,因为如此一来我们就能够将不同的启动管理程序安装到个别的文件系统最前端,而不用覆盖整颗硬盘唯一的 MBR, 这样也才能够制作出多重引导的环境啊!
至于每一个区块群组(block group)的六个主要内容说明如后:

data block (数据区块)

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

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

除此之外 Ext2 文件系统的 block 还有什么限制呢?有的!基本限制如下:
原则上,block 的大小与数量在格式化完就不能够再改变了(除非重新格式化);
每个 block 内最多只能够放置一个文件的数据;
承上,如果文件大于 block 的大小,则一个文件会占用多个 block 数量;
承上,若文件小于 block ,则该 block 的剩余容量就不能够再被使用了(磁盘空间会浪费)。
由于每个 block 仅能容纳一个文件的数据而已,因此如果你的文件都非常小,但是你的 block 在格式化时却选用最大的 4K 时,可能会产生一些容量的浪费喔!

既然大的 block 可能会产生较严重的磁盘容量浪费,那么我们是否就将 block 大小订为 1K 即可? 这也不妥,因为如果 block 较小的话,那么大型文件将会占用数量更多的 block ,而 inode 也要记录更多的 block 号码,此时将可能导致文件系统不良的读写效能。

所以我们可以说,在您进行文件系统的格式化之前,请先想好该文件系统预计使用的情况。

inode table (inode 表格)

inode 的内容在记录文件的属性以及该文件实际数据是放置在哪几号 block 内! 基本上,inode 记录的文件数据至少有底下这些:
该文件的存取模式(read/write/excute);
该文件的拥有者与群组(owner/group);
该文件的容量;
该文件创建或状态改变的时间(ctime);
最近一次的读取时间(atime);
最近修改的时间(mtime);
定义文件特性的旗标(flag),如 SetUID...;
该文件真正内容的指向 (pointer);
inode 的数量与大小也是在格式化时就已经固定了,除此之外 inode 还有些什么特色呢?
每个 inode 大小均固定为 128 bytes;
每个文件都仅会占用一个 inode 而已;
承上,因此文件系统能够创建的文件数量与 inode 的数量有关;
系统读取文件时需要先找到 inode,并分析 inode 所记录的权限与用户是否符合,若符合才能够开始实际读取 block 的内容。

我们约略来分析一下 inode / block 与文件大小的关系好了。inode 要记录的数据非常多,但偏偏又只有 128bytes 而已, 而 inode 记录一个 block 号码要花掉 4byte ,假设我一个文件有 400MB 且每个 block 为 4K 时, 那么至少也要十万笔 block 号码的记录呢!inode 哪有这么多可记录的信息?为此我们的系统很聪明的将 inode 记录 block 号码的区域定义为12个直接,一个间接, 一个双间接与一个三间接记录区。这是啥?我们将 inode 的结构画一下好了。
inode

这样子 inode 能够指定多少个 block 呢?我们以较小的 1K block 来说明好了,可以指定的情况如下:

12 个直接指向: 12*1K=12K
由于是直接指向,所以总共可记录 12 笔记录,因此总额大小为如上所示;

间接: 256*1K=256K
每笔 block 号码的记录会花去 4bytes,因此 1K 的大小能够记录 256 笔记录,因此一个间接可以记录的文件大小如上;

双间接: 256*256*1K=2562K
第一层 block 会指定 256 个第二层,每个第二层可以指定 256 个号码,因此总额大小如上;

三间接: 256*256*256*1K=2563K
第一层 block 会指定 256 个第二层,每个第二层可以指定 256 个第三层,每个第三层可以指定 256 个号码,因此总额大小如上;

总额:将直接、间接、双间接、三间接加总,得到 12 + 256 + 256*256 + 256*256*256 (K) = 16GB

但这个方法不能用在 2K 及 4K block 大小的计算中, 因为大于 2K 的 block 将会受到 Ext2 文件系统本身的限制,所以计算的结果会不太符合之故。

Superblock (超级区块)

Superblock 是记录整个 filesystem 相关信息的地方, 没有 Superblock ,就没有这个 filesystem 了。他记录的信息主要有:
block 与 inode 的总量;
未使用与已使用的 inode / block 数量;
block 与 inode 的大小 (block 为 1, 2, 4K,inode 为 128 bytes);
filesystem 的挂载时间、最近一次写入数据的时间、最近一次检验磁盘 (fsck) 的时间等文件系统的相关信息;
一个 valid bit 数值,若此文件系统已被挂载,则 valid bit 为 0 ,若未被挂载,则 valid bit 为 1 。
注:Superblock 是非常重要的,因为我们这个文件系统的基本信息都写在这里,因此,如果 superblock 死掉了, 你的文件系统可能就需要花费很多时间去挽救啦!一般来说, superblock 的大小为 1024bytes。
此外,每个 block group 都可能含有 superblock !但是我们也说一个文件系统应该仅有一个 superblock 而已。 事实上除了第一个 block group 内会含有 superblock 之外,后续的 block group 不一定含有 superblock , 而若含有 superblock 则该 superblock 主要是做为第一个 block group 内 superblock 的备份,这样可以进行 superblock 的救援!相关的 superblock 信息我们等一下会以 dumpe2fs 命令来呼叫出来观察喔!

Filesystem Description (文件系统描述说明)

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

block bitmap (区块对照表)

新增文件时,透过 block bitmap 的辅助,从 block bitmap 当中可以知道哪些 block 是空的,因此我们的系统就能够很快速的找到可使用的空间来处置文件啰。
删除文件时,那么那些文件原本占用的 block 号码就得要释放出来, 此时在 block bitmap 当中相对应到该 block 号码的标志就得要修改成为『未使用中』啰!这就是 bitmap 的功能。

inode bitmap (inode 对照表)

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

了解了文件系统的概念之后,再来当然是观察这个文件系统啰!刚刚谈到的各部分数据都与 block 号码有关! 每个区段与 superblock 的信息都可以使用 dumpe2fs 这个命令来查询的!查询的方法与实际的观察如下:

[root@www ~]# dumpe2fs [-bh] 装置文件名
选项与参数:
-b :列出保留为坏轨的部分(一般用不到吧!?)
-h :仅列出 superblock 的数据,不会列出其他的区段内容!

范例:找出我的根目录磁盘文件名,并观察文件系统的相关信息
[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/shm

[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 01:49:20 2008
First inode:              11
Inode 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)
....(底下省略)....
# 由于数据量非常的庞大,因此鸟哥将一些信息省略输出了!上表与你的屏幕会有点差异。
# 前半部在秀出 supberblock 的内容,包括标头名称(Label)以及inode/block的相关信息
# 后面则是每个 block group 的个别信息了!您可以看到各区段数据所在的号码!
# 也就是说,基本上所有的数据还是与 block 的号码有关就是了!很重要!

至于 block group 的内容我们单纯看 Group0 信息好了。从上表中我们发现:
Group0 所占用的 block 号码由 0 到 32767 号, superblock 则在第 0 号的 block 区块内
文件系统描述说明在第 1 号 block 中
block bitmap 与 inode bitmap 则在 627 及 628 的 block 号码上
至于 inode table 分布于 629-1641 的 block 号码中
由于(1)一个 inode 占用 128 bytes,(2)总共有1641 - 629 + 1(629 本身) = 1013 个 block 花在 inode table 上,(3)每个 block 的大小为 4096 bytes(4K)。由这些数据可以算出 inode 的数量共有 1013 * 4096 / 128 = 32416 个 inode
这个 Group0 目前没有可用的 block 了,但是有剩余 32405 个 inode 未被使用
剩余的 inode 号码为 12 号到 32416 号。

1.4 与目录树的关系

目录:

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

如果想要实际观察 root 家目录内的文件所占用的 inode 号码时,可以使用 ls -i 这个选项来处理。
当你使用『 ll / 』时,出现的目录几乎都是 1024 的倍数,为什么呢?因为每个 block 的数量都是 1K, 2K, 4K 嘛! 看一下鸟哥的环境:

[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 <==四个 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       <==三个 4K block

文件:

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

目录树读取:

经过上面的说明你也应该要很清楚的知道 inode 本身并不记录文件名,文件名的记录是在目录的 block 当中。 因此在第六章文件与目录的权限说明中, 我们才会提到『新增/删除/更名文件名与目录的 w 权限有关』的特色!那么因为文件名是记录在目录的 block 当中, 因此当我们要读取某个文件时,就务必会经过目录的 inode 与 block ,然后才能够找到那个待读取文件的 inode 号码, 最终才会读到正确的文件的 block 内的数据。

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

举例来说,如果我想要读取 /etc/passwd 这个文件时,系统是如何读取的呢?

[root@www ~]# ll -di / /etc /etc/passwd
      2 drwxr-xr-x  23 root root  4096 Sep 22 12:09 /
1912545 drwxr-xr-x 105 root root 12288 Oct 14 04:02 /etc
1914888 -rw-r--r--   1 root root  1945 Sep 29 02:21 /etc/passwd

在鸟哥的系统上面与 /etc/passwd 有关的目录与文件数据如上表所示,该文件的读取流程为(假设读取者身份为 vbird 这个一般身份使用者):

/ 的 inode:
透过挂载点的信息找到 /dev/hdc2 的 inode 号码为 2 的根目录 inode,且 inode 规范的权限让我们可以读取该 block 的内容(有 r 与 x) ;
/ 的 block:
经过上个步骤取得 block 的号码,并找到该内容有 etc/ 目录的 inode 号码 (1912545);
etc/ 的 inode:
读取 1912545 号 inode 得知 vbird 具有 r 与 x 的权限,因此可以读取 etc/ 的 block 内容;
etc/ 的 block:
经过上个步骤取得 block 号码,并找到该内容有 passwd 文件的 inode 号码 (1914888);
passwd 的 inode:
读取 1914888 号 inode 得知 vbird 具有 r 的权限,因此可以读取 passwd 的 block 内容;
passwd 的 block:
最后将该 block 内容的数据读出来。

filesystem 大小与磁盘读取效能

整个文件系统上面的文件通常无法连续写在一起(block 号码不会连续的意思), 而是填入式的将数据填入没有被使用的 block 当中。如果文件写入的 block 真的分的很散, 此时就会有所谓的文件数据离散的问题发生了。
如果文件真的太过离散,确实还是会发生读取效率低落的问题。 因为磁盘读取头还是得要在整个文件系统中来来去去的频繁读取! 果真如此,那么可以将整个 filesystme 内的数据全部复制出来,将该 filesystem 重新格式化, 再将数据给他复制回去即可解决这个问题。
因此, partition 的规划并不是越大越好, 而是真的要针对您的主机用途来进行规划才行!

1.5 EXT2/EXT3 文件的存取与日志式文件系统的功能

新建一个文件或目录时,我们的 Ext2 是如何处理的呢? 这个时候就得要 block bitmap 及 inode bitmap 的帮忙了!假设我们想要新增一个文件,此时文件系统的行为是:

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 称为数据存放区域,
中介数据:
至于其他例如 superblock、 block bitmap 与 inode bitmap 等区段就被称为 metadata (中介数据) ,因为 superblock, inode bitmap 及 block bitmap 的数据是经常变动的,每次新增、移除、编辑时都可能会影响到这三个部分的数据,因此才被称为中介数据的啦。

数据的不一致(inconsistent)状态:(出现问题)

产生数据不一致的情况,例如你的文件在写入文件系统时,因为不知名原因导致系统中断(例如突然的停电啊、 系统核心发生错误啊~等等的怪事发生时),所以写入的数据仅有 inode table 及 data block 而已, 最后一个同步升级中介数据的步骤并没有做完,此时就会发生 metadata 的内容与实际数据存放区产生不一致 (Inconsistent) 的情况了。

在早期的 Ext2 文件系统中,如果发生这个问题, 那么系统在重新启动的时候,就会藉由 Superblock 当中记录的 valid bit (是否有挂载) 与 filesystem state (clean 与否) 等状态来判断是否强制进行数据一致性的检查!若有需要检查时则以 e2fsck 这支程序来进行的。这样的检查真的是很费时~因为要针对 metadata 区域与实际数据存放区来进行比对。

日志式文件系统(Journaling filesystem):(解决问题)

为了避免上述提到的文件系统不一致的情况发生,因此我们的前辈们想到一个方式, 在 filesystem 当中规划出一个区块,专门记录写入或修订文件时的步骤,就可以简化一致性检查的步骤。即:

1、预备:当系统要写入一个文件时,会先在日志记录区块中纪录某个文件准备要写入的信息;
2、实际写入:开始写入文件的权限与数据;开始升级 metadata 的数据;
3、结束:完成数据与 metadata 的升级后,在日志记录区块当中完成该文件的纪录。

在这样的程序当中,万一数据的纪录过程当中发生了问题,那么我们的系统只要去检查日志记录区块, 就可以知道哪个文件发生了问题,针对该问题来做一致性的检查即可,而不必针对整块 filesystem 去检查, 这样就可以达到快速修复 filesystem 的能力了!这就是日志式文件最基础的功能啰~

『为什么你想要从ext2转换到ext3呢?有四个主要的理由:可利用性、数据完整性、速度及易于转换』 『可利用性』,他指出,这意味着从系统中止到快速重新复原而不是持续的让e2fsck运行长时间的修复。ext3 的日志式条件可以避免数据毁损的可能。他也指出: 『除了写入若干数据超过一次时,ext3往往会较快于ext2,因为ext3的日志使硬盘读取头的移动能更有效的进行』 然而或许决定的因素还是在Johnson先生的第四个理由中。

『它是可以轻易的从ext2变更到ext3来获得一个强而有力的日志式文件系统而不需要重新做格式化』。『那是正确的,为了体验一下 ext3 的好处是不需要去做一种长时间的,冗长乏味的且易于产生错误的备份工作及重新格式化的动作』。

1.6 Linux 文件系统的运行

如果你常常编辑一个好大的文件, 在编辑的过程中又频繁的要系统来写入到磁盘中,由于磁盘写入的速度要比内存慢很多, 因此你会常常耗在等待硬盘的写入/读取上。真没效率!
为了解决这个效率的问题, Linux 透过一个称为异步处理 (asynchronously) 的方式。所谓的异步处理是这样的:
当系统加载一个文件到内存后,如果该文件没有被更改,则在内存区段的文件数据会被配置为干净(clean)的。但如果内存中的文件被更改过了,此时该内存中的数据会被配置为脏(dirty)的。此时所有的动作都还在内存中运行,并没有写到磁盘上。此外,系统会不定时的将内存中配置为 dirty 的数据写回磁盘,以保持磁盘与内存数据的一致性。也可以用 sync 命令来手动强迫写入磁盘。

我们知道内存的速度要比硬盘快的多,因此如果能够将常用的文件放置到内存当中,这不就会添加系统性能吗? 没错!是有这样的想法!因此我们 Linux 系统上面文件系统与内存有非常大的关系喔:

系统会将常用的文件数据放置到主存储器的缓冲区,以加速文件系统的读/写;
承上,因此 Linux 的物理内存最后都会被用光!这是正常的情况!可加速系统效能;
你可以手动使用 sync 来强迫内存中配置为 Dirty 的文件回写到磁盘中;
若正常关机时,关机命令会主动呼叫 sync 来将内存的数据回写入磁盘内;
但若不正常关机(如跳电、死机或其他不明原因),由于数据尚未回写到磁盘内, 因此重新启动后可能会花很多时间在进行磁盘检验,甚至可能导致文件系统的损毁(非磁盘损毁)。

1.7 挂载点的意义 (mount point)

每个 filesystem 都有独立的 inode / block / superblock 等信息,这个文件系统要能够链接到目录树才能被我们使用。将文件系统与目录树结合的动作我们称为『挂载』。重点是:挂载点一定是目录,该目录为进入该文件系统的入口。

那如果观察这三个目录的 inode 号码时,我们可以发现如下的情况:

[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

看到了吧!由于 filesystem 最顶层的目录之 inode 一般为 2 号,因此可以发现 /, /boot, /home 为三个不同的 filesystem 啰! (因为每一行的文件属性并不相同,且三个目录的挂载点也均不相同之故。)

我们在第七章一开始的路径中曾经提到根目录下的 . 与 .. 是相同的东西, 因为权限是一模一样嘛!如果使用文件系统的观点来看,同一个 filesystem 的某个 inode 只会对应到一个文件内容而已(因为一个文件占用一个 inode 之故), 因此我们可以透过判断 inode 号码来确认不同文件名是否为相同的文件喔!所以可以这样看:

[root@www ~]# ls -ild /  /.  /..
2 drwxr-xr-x 23 root root 4096 Sep 22 12:09 /
2 drwxr-xr-x 23 root root 4096 Sep 22 12:09 /.
2 drwxr-xr-x 23 root root 4096 Sep 22 12:09 /..

上面的信息中由于挂载点均为 / ,因此三个文件 (/, /., /..) 均在同一个 filesystem 内,而这三个文件的 inode 号码均为 2 号,因此这三个档名都指向同一个 inode 号码,当然这三个文件的内容也就完全一模一样了! 也就是说,根目录的上一级 (/..) 就是他自己!

1.8 其他 Linux 支持的文件系统与 VFS

那么 Linux 的核心又是如何管理这些认识的文件系统呢? 其实,整个 Linux 的系统都是透过一个名为 Virtual Filesystem Switch 的核心功能去读取 filesystem 的。
整个 VFS 可以约略用下图来说明:
VFS

  1. 文件系统的简单操作

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

我们知道磁盘的整体数据是在 superblock 区块中,但是每个各别文件的容量则在 inode 当中记载的。
下面谈谈这两个命令:
df:列出文件系统的整体磁盘使用量;
du:评估文件系统的磁盘使用量(常用在推估目录所占容量)

df
[root@www ~]# df [-ahikHTm] [目录或文件名]
选项与参数:
-a  :列出所有的文件系统,包括系统特有的 /proc 等文件系统;
-k  :以 KBytes 的容量显示各文件系统;
-m  :以 MBytes 的容量显示各文件系统;
-h  :以人们较易阅读的 GBytes, MBytes, KBytes 等格式自行显示;
-H  :以 M=1000K 取代 M=1024K 的进位方式;
-T  :连同该 partition 的 filesystem 名称 (例如 ext3) 也列出;
-i  :不用硬盘容量,而以 inode 的数量来显示

范例一:将系统内所有的 filesystem 列出来!
[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 Kbytes 的容量来列出来!
# 至于那个 /dev/shm 是与内存有关的挂载,先不要理他!

范例二:将容量结果以易读的容量格式显示出来
[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 等容量格式显示出来,比较容易看啦!

范例三:将系统内的所有特殊文件格式及名称都列出来
[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 这个挂载点。因此,这些特殊的文件系统
# 都不会占据硬盘空间喔! ^_^

范例四:将 /etc 底下的可用的磁盘容量以易读的容量格式显示
[root@www ~]# df -h /etc
Filesystem            Size  Used Avail Use% Mounted on
/dev/hdc2             9.5G  3.7G  5.4G  41% /
# 这个范例比较有趣一点啦,在 df 后面加上目录或者是文件时, df
# 会自动的分析该目录或文件所在的 partition ,并将该 partition 的容量显示出来,
# 所以,您就可以知道某个目录底下还有多少容量可以使用了! ^_^

范例五:将目前各个 partition 当中可用的 inode 数量列出
[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 还要多呢

由于 df 主要读取的数据几乎都是针对一整个文件系统,因此读取的范围主要是在 Superblock 内的信息, 所以这个命令显示结果的速度非常的快速!
注意:如果使用 -a 这个参数时,系统会出现 /proc 这个挂载点,但是里面的东西都是 0 , /proc 的东西都是 Linux 系统所需要加载的系统数据,而且是挂载在『内存当中』的, 所以当然没有占任何的硬盘空间啰!
那个 /dev/shm/ 目录,其实是利用内存虚拟出来的磁盘空间! 由于是透过内存仿真出来的磁盘,因此你在这个目录底下创建任何数据文件时,访问速度是非常快速的!(在内存内工作) 不过,也由于他是内存仿真出来的,因此这个文件系统的大小在每部主机上都不一样,而且创建的东西在下次启动时就消失了! 因为是在内存中嘛!

du
[root@www ~]# du [-ahskm] 文件或目录名称
选项与参数:
-a  :列出所有的文件与目录容量,因为默认仅统计目录底下的文件量而已。
-h  :以人们较易读的容量格式 (G/M) 显示;
-s  :列出总量而已,而不列出每个各别的目录占用容量;
-S  :不包括子目录下的总计,与 -s 有点差别。
-k  :以 KBytes 列出容量显示;
-m  :以 MBytes 列出容量显示;

范例一:列出目前目录下的所有文件容量
[root@www ~]# du
8       ./test4     <==每个目录都会列出来
8       ./test2
....中间省略....
12      ./.gconfd   <==包括隐藏文件的目录
220     .           <==这个目录(.)所占用的总量
# 直接输入 du 没有加任何选项时,则 du 会分析『目前所在目录』
# 的文件与目录所占用的硬盘空间。但是,实际显示时,仅会显示目录容量(不含文件),
# 因此 . 目录有很多文件没有被列出来,所以全部的目录相加不会等于 . 的容量喔!
# 此外,输出的数值数据为 1K 大小的容量单位。

范例二:同范例一,但是将文件的容量也列出来
[root@www ~]# du -a
12      ./install.log.syslog   <==有文件的列表了
8       ./.bash_logout
8       ./test4
8       ./test2
....中间省略....
12      ./.gconfd
220     .

范例三:检查根目录底下每个目录所占用的容量
[root@www ~]# du -sm /*
7       /bin
6       /boot
.....中间省略....
0       /proc
.....中间省略....
1       /tmp
3859    /usr     <==系统初期最大就是他了啦!
77      /var
# 这是个很常被使用的功能~利用通配符 * 来代表每个目录,
# 如果想要检查某个目录下,哪个次目录占用最大的容量,可以用这个方法找出来
# 值得注意的是,如果刚刚安装好 Linux 时,那么整个系统容量最大的应该是 /usr 
# 而 /proc 虽然有列出容量,但是那个容量是在内存中,不占硬盘空间。

与 df 不一样的是,du 这个命令其实会直接到文件系统内去搜寻所有的文件数据, 所以上述第三个范例命令的运行会运行一小段时间!此外,在默认的情况下,容量的输出是以 KB 来设计的, 如果你想要知道目录占了多少 MB ,那么就使用 -m 这个参数即可啰!而, 如果你只想要知道该目录占了多少容量的话,使用 -s 就可以啦!
至于 -S 这个选项部分,由于 du 默认会将所有文件的大小均列出,因此假设你在 /etc 底下使用 du 时, 所有的文件大小,包括 /etc 底下的次目录容量也会被计算一次。然后最终的容量 (/etc) 也会加总一次, 因此很多朋友都会误会 du 分析的结果不太对劲。所以啰,如果想要列出某目录下的全部数据, 或许也可以加上 -S 的选项,减少次目录的加总喔!

2.2 实体链接与符号链接: ln

Hard Link (实体链接, 硬式连结或实际连结):

在前一小节当中,我们知道几件重要的信息,包括:

每个文件都会占用一个 inode ,文件内容由 inode 的记录来指向;
想要读取该文件,必须要经过目录记录的文件名来指向到正确的 inode 号码才能读取。

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

[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

也就是说,其实文件名只与目录有关,但是文件内容则与 inode 有关。
hard link 只是在某个目录下新增一笔档名链接到某 inode 号码的关连记录而已。

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

一般来说,使用 hard link 配置链接文件时,磁盘的空间与 inode 的数目都不会改变! (除非新增的这笔数据刚好将目录的 block 填满)我们还是由图 2.2.1 来看,由图中可以知道,
hard link 只是在某个目录下的 block 多写入一个关连数据而已,既不会添加 inode 也不会耗用 block 数量哩!

hard link 是有限制的:
1、不能跨 Filesystem
2、不能 link 目录(这是因为如果使用 hard link 链接到目录时, 链接的数据需要连同被链接目录底下的所有数据都创建链接)

Symbolic Link (符号链接,亦即是快捷方式):

symbolic link 就是在创建一个独立的文件,而这个文件会让数据的读取指向他 link 的那个文件的档名!
由于只是利用文件来做为指向的动作, 所以,当来源档被删除之后,symbolic link 的文件会『开不了』, 会一直说『无法开启某文件!』。实际上就是找不到原始『档名』而已啦!

举例来说,我们先创建一个符号链接文件链接到 /etc/crontab 去看看:

[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

连结档的重要内容就是他会写上目标文件的『文件名』, 你可以发现为什么上表中连结档的大小为 12 bytes 呢? 因为箭头(-->)右边的档名『/etc/crontab』总共有 12 个英文,每个英文占用 1 个 btyes ,所以文件大小就是 12bytes了。

Symbolic Link 与 Windows 的快捷方式可以给他划上等号,由 Symbolic link 所创建的文件为一个独立的新的文件,所以会占用掉 inode 与 block

ln
[root@www ~]# ln [-sf] 来源文件 目标文件
选项与参数:
-s  :如果不加任何参数就进行连结,那就是hard link,至于 -s 就是symbolic link
-f  :如果 目标文件 存在时,就主动的将目标文件直接移除后再创建!

范例一:将 /etc/passwd 复制到 /tmp 底下,并且观察 inode 与 block
[root@www ~]# cd /tmp
[root@www tmp]# cp -a /etc/passwd .
[root@www tmp]# du -sb ; df -i .
18340   .  <==先注意一下这里的容量是多少!
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
586361 -rw-r--r-- 2 root root 1945 Sep 29 02:21 passwd-hd
586401 lrwxrwxrwx 1 root root    6 Oct 22 14:18 passwd-so -> passwd
# passwd-so 指向的 inode number 不同了!这是一个新的文件~这个文件的内容是指向 
# passwd 的。passwd-so 的大小是 6bytes ,因为 passwd 共有六个字符之故

[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 -s /bin /root/bin
那么如果你进入 /root/bin 这个目录下,『请注意呦!该目录其实是 /bin 这个目录,因为你做了连结档了!』所以,如果你进入 /root/bin 这个刚刚创建的链接目录, 并且将其中的数据杀掉时,嗯! /bin 里面的数据就通通不见了!这点请千万注意!所以赶紧利用『rm /root/bin 』 将这个连结档删除吧!

关于目录的 link 数量:

当我们创建一个新目录名称为 /tmp/testing 时,基本上会有三个东西,那就是:

/tmp/testing
/tmp/testing/.
/tmp/testing/..
而其中 /tmp/testing 与 /tmp/testing/. 其实是一样的!都代表该目录啊~而 /tmp/testing/.. 则代表 /tmp 这个目录,所以说,当我们创建一个新的目录时, 『新的目录的 link 数为 2 ,而上一级目录的 link 数则会添加 1 』 不信的话,我们来作个测试看看:
[root@www ~]# ls -ld /tmp
drwxrwxrwt 5 root root 4096 Oct 22 14:22 /tmp
[root@www ~]# mkdir /tmp/testing1
[root@www ~]# ls -ld /tmp
drwxrwxrwt 6 root root 4096 Oct 22 14:37 /tmp
[root@www ~]# ls -ld /tmp/testing1
drwxr-xr-x 2 root root 4096 Oct 22 14:37 /tmp/testing1
  1. 磁盘的分割、格式化、检验与挂载

3.1 磁盘分区: fdisk, partprobe
3.2 磁盘格式化: mkfs, mke2fs
3.3 磁盘检验: fsck, badblocks
3.4 磁盘挂载与卸除: mount, umount
3.5 磁盘参数修订: mknod, e2label, tune2fs, hdparm

如果我们想要在系统里面新增一颗硬盘时,应该有哪些动作需要做的呢:
1、对磁盘进行分割,以创建可用的 partition ;
2、对该 partition 进行格式化( format ),以创建系统可用的 filesystem;
3、若想要仔细一点,则可对刚刚创建好的 filesystem 进行检验;
4、在 Linux 系统上,需要创建挂载点 ( 亦即是目录 ),并将他挂载上来;

当然啰,在上述的过程当中,还有很多需要考虑的,例如磁盘分区槽 (partition) 需要定多大? 是否需要加入 journal 的功能?inode 与 block 的数量应该如何规划等等的问题。但是这些问题的决定, 都需要与你的主机用途来加以考虑的~

3.1 磁盘分区: fdisk, partprobe

磁盘分区: fdisk

[root@www ~]# fdisk [-l] 装置名称
选项与参数:
-l  :输出后面接的装置所有的 partition 内容。若仅有 fdisk -l 时,
      则系统将会把整个系统内能够搜寻到的装置的 partition 均列出来。

范例:找出你系统中的根目录所在磁盘,并查阅该硬盘内的相关信息
[root@www ~]# df /            <==注意:重点在找出磁盘文件名而已
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/hdc2              9920624   3823168   5585388  41% /

[root@www ~]# fdisk /dev/hdc  <==仔细看,不要加上数字喔!
The number of cylinders for this disk is set to 5005.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)

Command (m for help):     <==等待你的输入!

Command (m for help): m   <== 输入 m 后,就会看到底下这些命令介绍
Command action
   a   toggle a bootable flag
   b   edit bsd disklabel
   c   toggle the dos compatibility flag
   d   delete a partition            <==删除一个partition
   l   list known partition types
   m   print this menu
   n   add a new partition           <==新增一个partition
   o   create a new empty DOS partition table
   p   print the partition table     <==在屏幕上显示分割表
   q   quit without saving changes   <==不储存离开fdisk程序
   s   create a new empty Sun disklabel
   t   change a partition's system id
   u   change display/entry units
   v   verify the partition table
   w   write table to disk and exit  <==将刚刚的动作写入分割表
   x   extra functionality (experts only)
注:不管你进行了什么动作,只要离开 fdisk 时按下『q』,那么所有的动作『都不会生效!』相反的, 按下『w』就是动作生效的意思。
先来看看分割表信息吧!
Command (m for help): p  <== 这里可以输出目前磁盘的状态

Disk /dev/hdc: 41.1 GB, 41174138880 bytes        <==这个磁盘的文件名与容量
255 heads, 63 sectors/track, 5005 cylinders      <==磁头、扇区与磁柱大小
Units = cylinders of 16065 * 512 = 8225280 bytes <==每个磁柱的大小

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc1   *           1          13      104391   83  Linux
/dev/hdc2              14        1288    10241437+  83  Linux
/dev/hdc3            1289        1925     5116702+  83  Linux
/dev/hdc4            1926        5005    24740100    5  Extended
/dev/hdc5            1926        2052     1020096   82  Linux swap / Solaris
# 装置文件名 启动区否 开始磁柱    结束磁柱  1K大小容量 磁盘分区槽内的系统

Command (m for help): q
# 想要不储存离开吗?按下 q 就对了!不要随便按 w 啊!

使用『 p 』可以列出目前这颗磁盘的分割表信息,这个信息的上半部在显示整体磁盘的状态。
下半部的分割表信息主要在列出每个分割槽的个别信息项目。每个项目的意义为:
1、Device:装置文件名,依据不同的磁盘接口/分割槽位置而变。
2、Boot:是否为启动引导块?通常 Windows 系统的 C 需要这块!
3、Start, End:这个分割槽在哪个磁柱号码之间,可以决定此分割槽的大小;
4、Blocks:就是以 1K 为单位的容量。如上所示,/dev/hdc1 大小为104391K = 102MB
5、ID, System:代表这个分割槽内的文件系统应该是啥!不过这个项目只是一个提示而已, 不见得真的代表此分割槽内的文件系统喔!

从上表我们可以发现几件事情:
1、整部磁盘还可以进行额外的分割,因为最大磁柱为 5005 ,但只使用到 2052 号而已;
2、/dev/hdc5 是由 /dev/hdc4 分割出来的,因为 /dev/hdc4 为 Extended,且 /dev/hdc5 磁柱号码在 /dev/hdc4 之内;
这个 fdisk 只有 root 才能运行,此外,请注意, 使用的『装置文件名』请不要加上数字,因为 partition 是针对『整个硬盘装置』而不是某个 partition 呢!所以运行『 fdisk /dev/hdc1 』 就会发生错误啦!要使用 fdisk /dev/hdc 才对!

删除磁盘分区槽

如何将你的 /dev/hdc 全部的分割槽删除,应该怎么做?
    1、fdisk /dev/hdc :先进入 fdisk 画面;
    2、p :先看一下分割槽的信息,假设要杀掉 /dev/hdc1;
    3、d :这个时候会要你选择一个 partition ,就选 1 啰!
    3、w (or) q :按 w 可储存到磁盘数据表中,并离开 fdisk ;当然啰, 如果你反悔了,呵呵,直接按下 q 就可以取消刚刚的删除动作了!


# 练习一: 先进入 fdisk 的画面当中去!
[root@www ~]# fdisk /dev/hdc

# 练习二: 先看看整个分割表的情况是如何
Command (m for help): p

Disk /dev/hdc: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc1   *           1          13      104391   83  Linux
/dev/hdc2              14        1288    10241437+  83  Linux
/dev/hdc3            1289        1925     5116702+  83  Linux
/dev/hdc4            1926        5005    24740100    5  Extended
/dev/hdc5            1926        2052     1020096   82  Linux swap / Solaris

# 练习三: 按下 d 给他删除吧!
Command (m for help): d
Partition number (1-5): 4

Command (m for help): d
Partition number (1-4): 3

Command (m for help): p

Disk /dev/hdc: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc1   *           1          13      104391   83  Linux
/dev/hdc2              14        1288    10241437+  83  Linux
# 因为 /dev/hdc5 是由 /dev/hdc4 所衍生出来的逻辑分割槽,因此 /dev/hdc4 被删除,
# /dev/hdc5 就自动不见了!最终就会剩下两个分割槽而已喔!

Command (m for help): q
# 鸟哥这里仅是做一个练习而已,所以,按下 q 就能够离开啰~
新增磁盘分区槽

# 练习一: 进入 fdisk 的分割软件画面中,并删除所有分割槽:
[root@www ~]# fdisk /dev/hdc
Command (m for help): d
Partition number (1-5): 4

Command (m for help): d
Partition number (1-4): 3

Command (m for help): d
Partition number (1-4): 2

Command (m for help): d
Selected partition 1
# 由于最后仅剩下一个 partition ,因此系统主动选取这个 partition 删除去!

# 练习二: 开始新增,我们先新增一个 Primary  的分割槽,且指定为 4 号看看!
Command (m for help): n
Command action            <==因为是全新磁盘,因此只会问extended/primary而已
   e   extended
   p   primary partition (1-4)
p                         <==选择 Primary 分割槽
Partition number (1-4): 4 <==配置为 4 号!
First cylinder (1-5005, default 1): <==直接按下[enter]按键决定!
Using default value 1               <==启始磁柱就选用默认值!
Last cylinder or +size or +sizeM or +sizeK (1-5005, default 5005): +512M
# 这个地方有趣了!我们知道 partition 是由 n1 到 n2 的磁柱号码 (cylinder),
# 但磁柱的大小每颗磁盘都不相同,这个时候可以填入 +512M 来让系统自动帮我们找出
# 『最接近 512M 的那个 cylinder 号码』!因为不可能刚好等于 512MBytes 啦!
# 如上所示:这个地方输入的方式有两种:
# 1) 直接输入磁柱的号码,你得要自己计算磁柱/分割槽的大小才行;
# 2) 用 +XXM 来输入分割槽的大小,让系统自己捉磁柱的号码。
#    +与M是必须要有的,XX为数字

Command (m for help): p

Disk /dev/hdc: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc4               1          63      506016   83  Linux
# 注意!只有 4 号! 1 ~ 3 保留下来了!

# 练习三: 继续新增一个,这次我们新增 Extended 的分割槽好了!
Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
e    <==选择的是 Extended 喔!
Partition number (1-4): 1
First cylinder (64-5005, default 64): <=[enter]
Using default value 64
Last cylinder or +size or +sizeM or +sizeK (64-5005, default 5005): <=[enter]
Using default value 5005
# 还记得我们在第三章的磁盘分区表曾经谈到过的,扩展分配最好能够包含所有
# 未分割的区间;所以在这个练习中,我们将所有未配置的磁柱都给了这个分割槽喔!
# 所以在开始/结束磁柱的位置上,按下两个[enter]用默认值即可!

Command (m for help): p

Disk /dev/hdc: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc1              64        5005    39696615    5  Extended
/dev/hdc4               1          63      506016   83  Linux
# 如上所示,所有的磁柱都在 /dev/hdc1 里面啰!

# 练习四: 这次我们随便新增一个 2GB 的分割槽看看!
Command (m for help): n
Command action
   l   logical (5 or over)     <==因为已有 extended ,所以出现 logical 分割槽
   p   primary partition (1-4)
p   <==偷偷玩一下,能否新增主要分割槽
Partition number (1-4): 2
No free sectors available   <==肯定不行!因为没有多余的磁柱可供配置

Command (m for help): n
Command action
   l   logical (5 or over)
   p   primary partition (1-4)
l   <==乖乖使用逻辑分割槽吧!
First cylinder (64-5005, default 64): <=[enter]
Using default value 64
Last cylinder or +size or +sizeM or +sizeK (64-5005, default 5005): +2048M

Command (m for help): p

Disk /dev/hdc: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc1              64        5005    39696615    5  Extended
/dev/hdc4               1          63      506016   83  Linux
/dev/hdc5              64         313     2008093+  83  Linux
# 这样就新增了 2GB 的分割槽,且由于是 logical ,所以由 5 号开始!
Command (m for help): q
# 鸟哥这里仅是做一个练习而已,所以,按下 q 就能够离开啰~

由上面的一连串练习中,最重要的地方其实就在于创建分割槽的形式( primary/extended/logical )以及分割槽的大小了!一般来说创建分割槽的形式会有底下的数种状况:
1-4 号尚有剩余,且系统未有 extended:
此时会出现让你挑选 Primary / Extended 的项目,且你可以指定 1~4 号间的号码;
1-4 号尚有剩余,且系统有 extended:
此时会出现让你挑选 Primary / Logical 的项目;若选择 p 则你还需要指定 1~4 号间的号码; 若选择 l(L的小写) 则不需要配置号码,因为系统会自动指定逻辑分割槽的文件名号码;
1-4 没有剩余,且系统有 extended:
此时不会让你挑选分割槽类型,直接会进入 logical 的分割槽形式。

例题:
请依照你的系统情况,创建一个大约 1GB 左右的分割槽,并显示该分割槽的相关信息:
答:
鸟哥的磁盘为 /dev/hdc ,尚有剩余磁柱号码,因此可以这样做:

[root@www ~]# fdisk /dev/hdc
Command (m for help): n
First cylinder (2053-5005, default 2053): <==[enter]
Using default value 2053
Last cylinder or +size or +sizeM or +sizeK (2053-5005, default 5005): +2048M

Command (m for help): p

Disk /dev/hdc: 41.1 GB, 41174138880 bytes
255 heads, 63 sectors/track, 5005 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc1   *           1          13      104391   83  Linux
/dev/hdc2              14        1288    10241437+  83  Linux
/dev/hdc3            1289        1925     5116702+  83  Linux
/dev/hdc4            1926        5005    24740100    5  Extended
/dev/hdc5            1926        2052     1020096   82  Linux swap / Solaris
/dev/hdc6            2053        2302     2008093+  83  Linux

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or 
resource busy.
The kernel still uses the old table.
The new table will be used at the next reboot.
Syncing disks. <==见鬼了!竟然需要 reboot 才能够生效!我可不要重新启动!

[root@www ~]# partprobe  <==强制让核心重新捉一次 partition table

在这个实作题中,请务必要按下『 w 』这个动作!因为我们实际上确实要创建这个分割槽嘛! 但请仔细看一下最后的警告信息,因为我们的磁盘无法卸除(因为含有根目录),所以核心无法重新取得分割表信息, 因此此时系统会要求我们重新启动(reboot)以升级核心的分割表信息才行。

如上的练习中,最终写入分割表后竟然会让核心无法捉到分割表信息!此时你可以直接使用 reboot 来处理, 也可以使用 GNU 推出的工具程序来处置,那就是 partprobe 这个命令。这个命令的运行很简单, 他仅是告知核心必须要读取新的分割表而已,因此并不会在屏幕上出现任何信息才是! 这样一来,我们就不需要 reboot 啰!

操作环境的说明

以 root 的身份进行硬盘的 partition 时,最好是在单人维护模式底下比较安全一些, 此外,在进行 fdisk 的时候,如果该硬盘某个 partition 还在使用当中, 那么很有可能系统核心会无法重载硬盘的 partition table ,解决的方法就是将该使用中的 partition 给他卸除,然后再重新进入 fdisk 一遍,重新写入 partition table ,那么就可以成功啰!

注意事项:

另外在实作过程中请特别注意,因为 SATA 硬盘最多能够支持到 15 号的分割槽, IDE 则可以支持到 63 号。 但目前大家常见的系统都是 SATA 磁盘,因此在练习的时候千万不要让你的分割槽超过 15 号! 否则即使你还有剩余的磁柱容量,但还是会无法继续进行分割的喔!
另外需要特别留意的是,fdisk 没有办法处理大于 2TB 以上的磁盘分区槽! 这个问题比较严重!因为虽然 Ext3 文件系统已经支持达到 16TB 以上的磁盘,但是分割命令却无法支持。 此时你就得使用 parted 这个命令了!我们会在本章最后谈一谈这个命令的用法。

3.2 磁盘格式化: mkfs, mke2fs

分割完毕后自然就是要进行文件系统的格式化啰!

mkfs

[root@www ~]# mkfs [-t 文件系统格式] 装置文件名
选项与参数:
-t  :可以接文件系统格式,例如 ext3, ext2, vfat 等(系统有支持才会生效)

范例一:请将上个小节当中所制作出来的 /dev/hdc6 格式化为 ext3 文件系统
[root@www ~]# mkfs -t ext3 /dev/hdc6
mke2fs 1.39 (29-May-2006)
Filesystem label=                <==这里指的是分割槽的名称(label)
OS type: Linux
Block size=4096 (log=2)          <==block 的大小配置为 4K 
Fragment size=4096 (log=2)
251392 inodes, 502023 blocks     <==由此配置决定的inode/block数量
25101 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=515899392
16 block groups
32768 blocks per group, 32768 fragments per group
15712 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912

Writing inode tables: done
Creating journal (8192 blocks): done <==有日志记录
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 34 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
# 这样就创建起来我们所需要的 Ext3 文件系统了!简单明了!

[root@www ~]# mkfs[tab][tab]
mkfs         mkfs.cramfs  mkfs.ext2    mkfs.ext3    mkfs.msdos   mkfs.vfat
# 按下两个[tab],会发现 mkfs 支持的文件格式如上所示!可以格式化 vfat 喔!

mkfs 其实是个综合命令而已,事实上如同上表所示,当我们使用『 mkfs -t ext3 ...』时, 系统会去呼叫 mkfs.ext3 这个命令来进行格式化的动作啦!
鸟哥这个系统支持的文件系统格式化工具有『cramfs, ext2, ext3, msdoc, vfat』等, 而最常用的应该是 ext3, vfat 两种啦!
注: vfat 可以用在 Windows/Linux 共享的 U盘 闪盘啰

在格式化为 Ext3 的范例中,我们可以发现结果里面含有非常多的信息,由于我们没有详细指定文件系统的细部项目, 因此系统会使用默认值来进行格式化。
其中比较重要的部分为:文件系统的标头(Label)、Block的大小以及 inode 的数量。 如果你要指定这些东西,就得要了解一下 Ext2/Ext3 的公用程序,亦即 mke2fs 这个命令啰!

mke2fs

[root@www ~]# mke2fs [-b block大小] [-i block大小] [-L 标头] [-cj] 装置
选项与参数:
-b  :可以配置每个 block 的大小,目前支持 1024, 2048, 4096 bytes 三种;
-i  :多少容量给予一个 inode 呢?
-c  :检查磁盘错误,仅下达一次 -c 时,会进行快速读取测试;
      如果下达两次 -c -c 的话,会测试读写(read-write),会很慢~
-L  :后面可以接标头名称 (Label),这个 label 是有用的喔!e2label命令介绍会谈到~
-j  :本来 mke2fs 是 EXT2 ,加上 -j 后,会主动加入 journal 而成为 EXT3。

mke2fs 是一个很详细但是很麻烦的命令!因为里面的细部配置太多了!现在我们进行如下的假设:
这个文件系统的标头配置为:vbird_logical
我的 block 指定为 2048 大小;
每 8192 bytes 分配一个 inode ;
建置为 journal 的 Ext3 文件系统。

开始格式化 /dev/hdc6 结果会变成如下所示:

[root@www ~]# mke2fs -j -L "vbird_logical" -b 2048 -i 8192 /dev/hdc6
mke2fs 1.39 (29-May-2006)
Filesystem label=vbird_logical
OS type: Linux
Block size=2048 (log=1)
Fragment size=2048 (log=1)
251968 inodes, 1004046 blocks
50202 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=537919488
62 block groups
16384 blocks per group, 16384 fragments per group
4064 inodes per group
Superblock backups stored on blocks:
        16384, 49152, 81920, 114688, 147456, 409600, 442368, 802816

Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done
# 比较看看,跟上面的范例用默认值的结果,有什么不一样的啊?

其实 mke2fs 所使用的各项选项/参数也可以用在『 mkfs -t ext3 ... 』后面,因为最终使用的公用程序是相同的啦! 特别要注意的是 -b, -i 及 -j 这几个选项,尤其是 -j 这个选项,当没有指定 -j 的时候, mke2fs 使用 ext2 为格式化文件格式,若加入 -j 时,则格式化为 ext3 这个 Journaling 的 filesystem 呦!

老实说,如果没有特殊需求的话,使用『 mkfs -t ext3....』不但容易记忆,而且就非常好用啰!

3.3 磁盘检验: fsck, badblocks

如果文件系统真的发生错乱的话,那该如何是好?就...挽救啊!此时那个好用的 filesystem check, fsck 就得拿来仔细瞧瞧啰。

fsck

[root@www ~]# fsck [-t 文件系统] [-ACay] 装置名称
选项与参数:
-t  :如同 mkfs 一样,fsck 也是个综合软件而已!因此我们同样需要指定文件系统。
      不过由于现今的 Linux 太聪明了,他会自动的透过 superblock 去分辨文件系统,
      因此通常可以不需要这个选项的啰!请看后续的范例说明。
-A  :依据 /etc/fstab 的内容,将需要的装置扫瞄一次。/etc/fstab 于下一小节说明,
      通常启动过程中就会运行此一命令了。
-a  :自动修复检查到的有问题的扇区,所以你不用一直按 y 啰!
-y  :与 -a 类似,但是某些 filesystem 仅支持 -y 这个参数!
-C  :可以在检验的过程当中,使用一个直方图来显示目前的进度!

EXT2/EXT3 的额外选项功能:(e2fsck 这支命令所提供)
-f  :强制检查!一般来说,如果 fsck 没有发现任何 unclean 的旗标,不会主动进入
      细部检查的,如果您想要强制 fsck 进入细部检查,就得加上 -f 旗标啰!
-D  :针对文件系统下的目录进行优化配置。

范例一:强制的将前面我们创建的 /dev/hdc6 这个装置给他检验一下!
[root@www ~]# fsck -C -f -t ext3 /dev/hdc6 
fsck 1.39 (29-May-2006)
e2fsck 1.39 (29-May-2006)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
vbird_logical: 11/251968 files (9.1% non-contiguous), 36926/1004046 blocks
# 如果没有加上 -f 的选项,则由于这个文件系统不曾出现问题,
# 检查的经过非常快速!若加上 -f 强制检查,才会一项一项的显示过程。

范例二:系统有多少文件系统支持的 fsck 软件?
[root@www ~]# fsck[tab][tab]
fsck         fsck.cramfs  fsck.ext2    fsck.ext3    fsck.msdos   fsck.vfat

注意:通常只有身为 root 且你的文件系统有问题的时候才使用这个命令,否则在正常状况下使用此一命令, 可能会造成对系统的危害!

另外,如果你怀疑刚刚格式化成功的硬盘有问题的时后,也可以使用 fsck 来检查一硬盘呦!

注:由于 fsck 在扫瞄硬盘的时候,可能会造成部分 filesystem 的损坏,所以『运行 fsck 时, 被检查的 partition 务必不可挂载到系统上!亦即是需要在卸除的状态喔!!!!

lost+found目录:ext2/ext3 文件系统的最顶层(就是挂载点那个目录底下)会存在一个『lost+found』的目录吧! 该目录就是在当你使用 fsck 检查文件系统后,若出现问题时,有问题的数据会被放置到这个目录中喔! 所以理论上这个目录不应该会有任何数据,若系统自动产生数据在里面,那...你就得特别注意你的文件系统啰!

我们的系统实际运行的 fsck 命令,其实是呼叫 e2fsck 这个软件啦!可以 man e2fsck 找到更多的选项辅助喔!

badblocks

刚刚谈到的 fsck 是用来检验文件系统是否出错,至于 badblocks 则是用来检查硬盘或软盘扇区有没有坏轨的命令! 

[root@www ~]# badblocks -[svw] 装置名称
选项与参数:
-s  :在屏幕上列出进度
-v  :可以在屏幕上看到进度
-w  :使用写入的方式来测试,建议不要使用此一参数,尤其是待检查的装置已有文件时!

[root@www ~]# badblocks -sv /dev/hdc6
Checking blocks 0 to 2008093
Checking for bad blocks (read-only test): done
Pass completed, 0 bad blocks found.

3.4 磁盘挂载与卸除: mount, umount

本章一开始时的挂载点的意义当中提过挂载点是目录, 而这个目录是进入磁盘分区槽(其实是文件系统啦!)的入口就是了。不过要进行挂载前,你最好先确定几件事:
单一文件系统不应该被重复挂载在不同的挂载点(目录)中;
单一目录不应该重复挂载多个文件系统;
要作为挂载点的目录,理论上应该都是空目录才是。

尤其是上述的后两点!如果你要用来挂载的目录里面并不是空的,那么挂载了文件系统之后,原目录下的东西就会暂时的消失。 举个例子来说,假设你的 /home 原本与根目录 (/) 在同一个文件系统中,底下原本就有 /home/test 与 /home/vbird 两个目录。然后你想要加入新的硬盘,并且直接挂载 /home 底下,那么当你挂载上新的分割槽时,则 /home 目录显示的是新分割槽内的数据,至于原先的 test 与 vbird 这两个目录就会暂时的被隐藏掉了!注意喔!并不是被覆盖掉, 而是暂时的隐藏了起来,等到新分割槽被卸除之后,则 /home 原本的内容就会再次的跑出来啦!

而要将文件系统挂载到我们的 Linux 系统上,就要使用 mount 这个命令啦!

mount

[root@www ~]# mount -a
[root@www ~]# mount [-l]
[root@www ~]# mount [-t 文件系统] [-L Label名] [-o 额外选项] \
 [-n]  装置文件名  挂载点
选项与参数:
-a  :依照配置文件 /etc/fstab 的数据将所有未挂载的磁盘都挂载上来
-l  :单纯的输入 mount 会显示目前挂载的信息。加上 -l 可增列 Label 名称!
-t  :与 mkfs 的选项非常类似的,可以加上文件系统种类来指定欲挂载的类型。
      常见的 Linux 支持类型有:ext2, ext3, vfat, reiserfs, iso9660(光盘格式),
      nfs, cifs, smbfs(此三种为网络文件系统类型)
-n  :在默认的情况下,系统会将实际挂载的情况实时写入 /etc/mtab 中,以利其他程序
      的运行。但在某些情况下(例如单人维护模式)为了避免问题,会刻意不写入。
      此时就得要使用这个 -n 的选项了。
-L  :系统除了利用装置文件名 (例如 /dev/hdc6) 之外,还可以利用文件系统的标头名称
      (Label)来进行挂载。最好为你的文件系统取一个独一无二的名称吧!
-o  :后面可以接一些挂载时额外加上的参数!比方说账号、密码、读写权限等:
      ro, rw:       挂载文件系统成为只读(ro) 或可擦写(rw)
      async, sync:  此文件系统是否使用同步写入 (sync) 或异步 (async) 的
                    内存机制,请参考文件系统运行方式。默认为 async。
      auto, noauto: 允许此 partition 被以 mount -a 自动挂载(auto)
      dev, nodev:   是否允许此 partition 上,可创建装置文件? dev 为可允许
      suid, nosuid: 是否允许此 partition 含有 suid/sgid 的文件格式?
      exec, noexec: 是否允许此 partition 上拥有可运行 binary 文件?
      user, nouser: 是否允许此 partition 让任何使用者运行 mount ?一般来说,
                    mount 仅有 root 可以进行,但下达 user 参数,则可让
                    一般 user 也能够对此 partition 进行 mount 。
      defaults:     默认值为:rw, suid, dev, exec, auto, nouser, and async
      remount:      重新挂载,这在系统出错,或重新升级参数时,很有用!

挂载Ext2/Ext3文件系统

范例一:用默认的方式,将刚刚创建的 /dev/hdc6 挂载到 /mnt/hdc6 上面!
[root@www ~]# mkdir /mnt/hdc6
[root@www ~]# mount /dev/hdc6 /mnt/hdc6
[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
.....中间省略.....
/dev/hdc6              1976312     42072   1833836   3% /mnt/hdc6
# 看起来,真的有挂载!且文件大小约为 2GB 左右啦!

为什么可以这么方便呢(甚至不需要使用 -t 这个选项)?由于文件系统几乎都有 superblock , 我们的 Linux 可以透过分析 superblock 搭配 Linux 自己的驱动程序去测试挂载, 如果成功的套和了,就立刻自动的使用该类型的文件系统挂载起来啊!

那么系统有没有指定哪些类型的 filesystem 才需要进行上述的挂载测试呢? 主要是参考底下这两个文件:
/etc/filesystems:系统指定的测试挂载文件系统类型;
/proc/filesystems:Linux系统已经加载的文件系统类型。

那我怎么知道我的 Linux 有没有相关文件系统类型的驱动程序呢?我们 Linux 支持的文件系统之驱动程序都写在如下的目录中:
/lib/modules/$(uname -r)/kernel/fs/

例如 vfat 的驱动程序就写在『/lib/modules/$(uname -r)/kernel/fs/vfat/』这个目录下啦!
检查看看目前已挂载的文件系统状况吧!

范例二:观察目前『已挂载』的文件系统,包含各文件系统的Label名称
[root@www ~]# mount -l
/dev/hdc2 on / type ext3 (rw) [/1]
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
/dev/hdc3 on /home type ext3 (rw) [/home]
/dev/hdc1 on /boot type ext3 (rw) [/boot]
tmpfs on /dev/shm type tmpfs (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)
/dev/hdc6 on /mnt/hdc6 type ext3 (rw) [vbird_logical]
# 除了实际的文件系统外,很多特殊的文件系统(proc/sysfs...)也会被显示出来!
# 值得注意的是,加上 -l 选项可以列出如上特殊字体的标头(label)喔
以 /dev/hdc2 这个装置来说好了(上面表格的第一行), 他的意义是:『/dev/hdc2 是挂载到 / 目录,文件系统类型为 ext3 ,且挂载为可擦写 (rw) ,另外,这个 filesystem 有标头,名字(label)为 /1 』

挂载 CD 或 DVD 光盘

范例三:将你用来安装 Linux 的 CentOS 原版光盘拿出来挂载!
[root@www ~]# mkdir /media/cdrom
[root@www ~]# mount -t iso9660 /dev/cdrom /media/cdrom
[root@www ~]# mount /dev/cdrom /media/cdrom 
# 你可以指定 -t iso9660 这个光盘片的格式来挂载,也可以让系统自己去测试挂载!
# 所以上述的命令只要做一个就够了!但是目录的创建初次挂载时必须要进行喔!
 
[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
.....中间省略.....
/dev/hdd               4493152   4493152         0 100% /media/cdrom
# 因为我的光驱使用的是 /dev/hdd 的 IDE 接口之故!

光驱一挂载之后就无法退出光盘片了!除非你将他卸除才能够退出!

格式化与挂载软盘

范例四:格式化后挂载软盘到 /media/floppy/ 目录中。
[root@www ~]# mkfs -t vfat /dev/fd0
# 我们格式化软盘成为 Windows/Linux 可共同使用的 FAT 格式吧!
[root@www ~]# mkdir /media/floppy
[root@www ~]# mount -t vfat /dev/fd0 /media/floppy
[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
.....中间省略.....
/dev/fd0                  1424       164      1260  12% /media/floppy

与光驱不同的是,你挂载了软盘后竟然还是可以退出软盘喔!不过,如此一来你的文件系统将会有莫名奇妙的问题发生! 整个 Linux 最重要的就是文件系统,而文件系统是直接挂载到目录树上头, 几乎任何命令都会或多或少使用到目录树的数据,因此你当然不可以随意的将光盘/软盘拿出来!
所以,软盘也请卸除之后再退出!很重要的一点!

挂载闪盘

范例五:找出你的闪盘装置文件名,并挂载到 /mnt/flash 目录中
[root@www ~]# fdisk -l
.....中间省略.....
Disk /dev/sda: 8313 MB, 8313110528 bytes
59 heads, 58 sectors/track, 4744 cylinders
Units = cylinders of 3422 * 512 = 1752064 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1               1        4745     8118260    b  W95 FAT32
# 从上的特殊字体,可得知磁盘的大小以及装置文件名,知道是 /dev/sda1 

[root@www ~]# mkdir /mnt/flash
[root@www ~]# mount -t vfat -o iocharset=cp950 /dev/sda1 /mnt/flash
[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
.....中间省略.....
/dev/sda1              8102416   4986228   3116188  62% /mnt/flash

如果带有中文文件名的数据,那么可以在挂载时指定一下挂载文件系统所使用的语系数据。 在 man mount 找到 vfat 文件格式当中可以使用 iocharset 来指定语系,而中文语系是 cp950 , 所以也就有了上述的挂载命令项目啰。

重新挂载根目录与挂载不特定目录

整个目录树最重要的地方就是根目录了,所以根目录根本就不能够被卸除的!问题是,如果你的挂载参数要改变, 或者是根目录出现『只读』状态时,如何重新挂载呢?最可能的处理方式就是重新启动 (reboot)! 不过你也可以这样做:

范例六:将 / 重新挂载,并加入参数为 rw 与 auto
[root@www ~]# mount -o remount,rw,auto /
  1. 配置启动挂载:

  4.1 启动挂载 /etc/fstab 及 /etc/mtab
  4.2 特殊装置 loop 挂载(映象档不刻录就挂载使用)

4.1 启动挂载 /etc/fstab 及 /etc/mtab
系统挂载的一些限制:
根目录 / 是必须挂载的﹐而且一定要先于其它 mount point 被挂载进来。
其它 mount point 必须为已创建的目录﹐可任意指定﹐但一定要遵守必须的系统目录架构原则
所有 mount point 在同一时间之内﹐只能挂载一次。
所有 partition 在同一时间之内﹐只能挂载一次。
如若进行卸除﹐您必须先将工作目录移到 mount point(及其子目录) 之外。

直接查阅一下 /etc/fstab 这个文件的内容吧!

[root@www ~]# cat /etc/fstab
# Device        Mount point   filesystem parameters    dump fsck
LABEL=/1          /           ext3       defaults        1 1
LABEL=/home       /home       ext3       defaults        1 2
LABEL=/boot       /boot       ext3       defaults        1 2
tmpfs             /dev/shm    tmpfs      defaults        0 0
devpts            /dev/pts    devpts     gid=5,mode=620  0 0
sysfs             /sys        sysfs      defaults        0 0
proc              /proc       proc       defaults        0 0
LABEL=SWAP-hdc5   swap        swap       defaults        0 0
# 上述特殊字体的部分与实际磁盘有关!其他则是虚拟文件系统或
# 与内存置换空间 (swap) 有关。

各个字段的详细数据如下:

第一栏:磁盘装置文件名或该装置的 Label:
这个字段请填入文件系统的装置文件名。
第二栏:挂载点 (mount point):
就是挂载点啊!挂载点是什么?一定是目录啊~要知道啊!
第三栏:磁盘分区槽的文件系统:
在手动挂载时可以让系统自动测试挂载,但在这个文件当中我们必须要手动写入文件系统才行! 包括 ext3, reiserfs, nfs, vfat 等等。
第四栏:文件系统参数:
async/sync
异步/同步 配置磁盘是否以异步方式运行!默认为 async(效能较佳)
auto/noauto
自动/非自动 当下达 mount -a 时,此文件系统是否会被主动测试挂载。默认为 auto。
rw/ro
可擦写/只读 让该分割槽以可擦写或者是只读的型态挂载上来,如果你想要分享的数据是不给用户随意变更的, 这里也能够配置为只读。则不论在此文件系统的文件是否配置 w 权限,都无法写入喔!
exec/noexec
可运行/不可运行 限制在此文件系统内是否可以进行『运行』的工作?如果是纯粹用来储存数据的, 那么可以配置为 noexec 会比较安全,相对的,会比较麻烦!
user/nouser
允许/不允许使用者挂载 是否允许用户使用 mount 命令来挂载呢?一般而言,我们当然不希望一般身份的 user 能使用 mount 啰,因为太不安全了,因此这里应该要配置为 nouser 啰!
suid/nosuid
具有/不具有 suid 权限 该文件系统是否允许 SUID 的存在?如果不是运行文件放置目录,也可以配置为 nosuid 来取消这个功能!
usrquota 注意名称是『 usrquota 』不要拼错了!这个是在启动 filesystem 支持磁盘配额模式,更多数据我们在第四篇再谈。
grpquota 注意名称是『grpquota』,启动 filesystem 对群组磁盘配额模式的支持。
defaults 同时具有 rw, suid, dev, exec, auto, nouser, async 等参数。 基本上,默认情况使用 defaults 配置即可!
第五栏:能否被 dump 备份命令作用:
dump 是一个用来做为备份的命令(我们会在第二十五章备份策略中谈到这个命令), 我们可以透过 fstab 指定哪个文件系统必须要进行 dump 备份! 0 代表不要做 dump 备份, 1 代表要每天进行 dump 的动作。 2 也代表其他不定日期的 dump 备份动作, 通常这个数值不是 0 就是 1 啦!
第六栏:是否以 fsck 检验扇区:
启动的过程中,系统默认会以 fsck 检验我们的 filesystem 是否完整 (clean)。 不过,某些 filesystem 是不需要检验的,例如内存置换空间 (swap) ,或者是特殊文件系统例如 /proc 与 /sys 等等。所以,在这个字段中,我们可以配置是否要以 fsck 检验该 filesystem 喔。 0 是不要检验, 1 表示最早检验(一般只有根目录会配置为 1), 2 也是要检验,不过 1 会比较早被检验啦! 一般来说,根目录配置为 1 ,其他的要检验的 filesystem 都配置为 2 就好了。

例题:
假设我们要将 /dev/hdc6 每次启动都自动挂载到 /mnt/hdc6 ,该如何进行?
答:
首先,请用 nano 将底下这一行写入 /etc/fstab 当中;

[root@www ~]# nano /etc/fstab
/dev/hdc6  /mnt/hdc6    ext3    defaults   1 2

再来看看 /dev/hdc6 是否已经挂载,如果挂载了,请务必卸除再说!

[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/hdc6              1976312     42072   1833836   3% /mnt/hdc6
# 竟然不知道何时被挂载了?赶紧给他卸除先!

[root@www ~]# umount /dev/hdc6

最后测试一下刚刚我们写入 /etc/fstab 的语法有没有错误!这点很重要!因为这个文件如果写错了, 则你的 Linux 很可能将无法顺利启动完成!所以请务必要测试测试喔!

[root@www ~]# mount -a				
// Mount all filesystems (of the given types) mentioned in fstab.
[root@www ~]# df

最终有看到 /dev/hdc6 被挂载起来的信息才是成功的挂载了!而且以后每次启动都会顺利的将此文件系统挂载起来的! 由于这个范例仅是测试而已,请务必回到 /etc/fstab 当中,将上述这行给他批注或者是删除掉!

[root@www ~]# nano /etc/fstab
# /dev/hdc6  /mnt/hdc6    ext3    defaults   1 2

/etc/fstab 是启动时的配置文件,不过,实际 filesystem 的挂载是记录到 /etc/mtab 与 /proc/mounts 这两个文件当中的。每次我们在更动 filesystem 的挂载时,也会同时更动这两个文件喔!但是,万一发生您在 /etc/fstab 输入的数据错误,导致无法顺利启动成功,而进入单人维护模式当中,那时候的 / 可是 read only 的状态,当然您就无法修改 /etc/fstab ,也无法升级 /etc/mtab 啰~那怎么办? 没关系,可以利用底下这一招:

[root@www ~]# mount -n -o remount,rw /

4.2 特殊装置 loop 挂载(映象档不刻录就挂载使用)

挂载光盘/DVD映象文件

想象一下如果今天我们从国家高速网络中心(http://ftp.twaren.net)或者是义守大学(http://ftp.isu.edu.tw)下载了 Linux 或者是其他所需光盘/DVD的映象文件后, 难道一定需要刻录成为光盘才能够使用该文件里面的数据吗?当然不是啦!我们可以透过 loop 装置来挂载的!

[root@www ~]# ll -h /root/centos5.2_x86_64.iso
-rw-r--r-- 1 root root 4.3G Oct 27 17:34 /root/centos5.2_x86_64.iso
# 看到上面的结果吧!这个文件就是映象档,文件非常的大吧!

[root@www ~]# mkdir /mnt/centos_dvd
[root@www ~]# mount -o loop /root/centos5.2_x86_64.iso /mnt/centos_dvd
[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/root/centos5.2_x86_64.iso
                       4493152   4493152         0 100% /mnt/centos_dvd
# 就是这个项目! .iso 映象文件内的所有数据可以在 /mnt/centos_dvd 看到!

[root@www ~]# ll /mnt/centos_dvd
total 584
drwxr-xr-x 2 root root 522240 Jun 24 00:57 CentOS <==瞧!就是DVD的内容啊!
-rw-r--r-- 8 root root    212 Nov 21  2007 EULA
-rw-r--r-- 8 root root  18009 Nov 21  2007 GPL
drwxr-xr-x 4 root root   2048 Jun 24 00:57 images
.....底下省略.....

[root@www ~]# umount /mnt/centos_dvd/
# 测试完成!记得将数据给他卸除!

如此一来我们不需要将这个文件刻录成为光盘或者是 DVD 就能够读取内部的数据了! 换句话说,你也可以在这个文件内『动手脚』去修改文件的!这也是为什么很多映象档提供后,还得要提供验证码 (MD5) 给使用者确认该映象档没有问题!

创建大文件以制作 loop 装置文件!

既然能够挂载 DVD 的映象档,那么我能不能制作出一个大文件,然后将这个文件格式化后挂载呢?
而且还能够帮助我们解决很多系统的分割不良的情况呢!举例来说,如果当初在分割时, 你只有分割出一个根目录,假设你已经没有多余的容量可以进行额外的分割的!偏偏根目录的容量还很大! 此时你就能够制作出一个大文件,然后将这个文件挂载!如此一来感觉上你就多了一个分割槽啰!

底下我们在 /home 下创建一个 512MB 左右的大文件,然后将这个大文件格式化并且实际挂载来玩一玩! 这样你会比较清楚鸟哥在讲啥!

1,创建大型文件

假设我要创建一个空的文件在 /home/loopdev ,那可以这样做:
[root@www ~]# dd if=/dev/zero of=/home/loopdev bs=1M count=512
512+0 records in   <==读入 512 笔数据
512+0 records out  <==输出 512 笔数据
536870912 bytes (537 MB) copied, 12.3484 seconds, 43.5 MB/s
# 这个命令的简单意义如下:
# if 是 input file ,输入文件。那个 /dev/zero 是会一直输出 0 的装置!
# of 是 output file ,将一堆零写入到后面接的文件中。
# bs 是每个 block 大小,就像文件系统那样的 block 意义;
# count 则是总共几个 bs 的意思。

[root@www ~]# ll -h /home/loopdev
-rw-r--r-- 1 root root 512M Oct 28 02:29 /home/loopdev

2,格式化
很简单就创建起一个 512MB 的文件了吶!接下来当然是格式化啰!

[root@www ~]# mkfs -t ext3 /home/loopdev
mke2fs 1.39 (29-May-2006)
/home/loopdev is not a block special device.
Proceed anyway? (y,n) y  <==由于不是正常的装置,所以这里会提示你!
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
131072 inodes, 524288 blocks
26214 blocks (5.00%) reserved for the super user
.....以下省略.....

3,挂载

那要如何挂载啊?利用 mount 的特殊参数,那个 -o loop 的参数来处理!

[root@www ~]# mount -o loop /home/loopdev /media/cdrom/
[root@www ~]# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/home/loopdev           507748     18768    462766   4% /media/cdrom

透过这个简单的方法,感觉上你就可以在原本的分割槽在不更动原有的环境下制作出你想要的分割槽就是了! 这东西很好用的!尤其是想要玩 Linux 上面的『虚拟机』的话, 也就是以一部 Linux 主机再切割成为数个独立的主机系统时,类似 VMware 这类的软件, 在 Linux 上使用 xen 这个软件,他就可以配合这种 loop device 的文件类型来进行根目录的挂载, 真的非常有用的喔! _

  1. 内存空间(swap)之建置

现在想象一个情况,你已经将系统创建起来了,此时却才发现你没有建置 swap ~那该如何是好呢? 透过本章上面谈到的方法,你可以使用如下的方式来创建你的 swap 啰!
配置一个 swap partition
创建一个虚拟内存的文件

5.1 使用实体分割槽建置swap

透过底下几个步骤就搞定啰:
1. 分割:先使用 fdisk 在你的磁盘中分割出一个分割槽给系统作为 swap 。由于 Linux 的 fdisk 默认会将分割槽的 ID 配置为 Linux 的文件系统,所以你可能还得要配置一下 system ID 就是了。
2. 格式化:利用创建 swap 格式的『mkswap 装置文件名』就能够格式化该分割槽成为 swap 格式啰
3. 使用:最后将该 swap 装置启动,方法为:『swapon 装置文件名』。
4. 观察:最终透过 free 这个命令来观察一下内存的用量吧!

1. 先进行分割的行为啰!
[root@www ~]# fdisk /dev/hdc
Command (m for help): n
First cylinder (2303-5005, default 2303):  <==这里按[enter]
Using default value 2303
Last cylinder or +size or +sizeM or +sizeK (2303-5005, default 5005): +256M

Command (m for help): p

   Device Boot      Start         End      Blocks   Id  System
.....中间省略.....
/dev/hdc6            2053        2302     2008093+  83  Linux
/dev/hdc7            2303        2334      257008+  83  Linux <==新增的项目

Command (m for help): t             <==修改系统 ID
Partition number (1-7): 7           <==从上结果看到的,七号partition
Hex code (type L to list codes): 82 <==改成 swap 的 ID
Changed system type of partition 7 to 82 (Linux swap / Solaris)

Command (m for help): p

   Device Boot      Start         End      Blocks   Id  System
.....中间省略.....
/dev/hdc6            2053        2302     2008093+  83  Linux
/dev/hdc7            2303        2334      257008+  82  Linux swap / Solaris

Command (m for help): w
# 此时就将 partition table 升级了!

[root@www ~]# partprobe
# 这个玩意儿很重要的啦!不要忘记让核心升级 partition table 喔!
2. 开始建置 swap 格式
[root@www ~]# mkswap /dev/hdc7
Setting up swapspace version 1, size = 263172 kB  <==非常快速!
3. 开始观察与加载看看吧!
[root@www ~]# free
             total       used       free     shared    buffers     cached
Mem:        742664     684592      58072          0      43820     497144
-/+ buffers/cache:     143628     599036
Swap:      1020088         96    1019992
# 我有 742664K 的物理内存,使用 684592K 剩余 58072K ,使用掉的内存有
# 43820K / 497144K 用在缓冲/缓存的用途中。
# 至于 swap 已经存在了 1020088K 啰!这样会看了吧?!

[root@www ~]# swapon /dev/hdc7
[root@www ~]# free
             total       used       free     shared    buffers     cached
Mem:        742664     684712      57952          0      43872     497180
-/+ buffers/cache:     143660     599004
Swap:      1277088         96    1276992  <==有添加啰!看到否?

[root@www ~]# swapon -s
Filename                 Type            Size    Used    Priority
/dev/hdc5                partition       1020088 96      -1
/dev/hdc7                partition       257000  0       -2
# 上面列出目前使用的 swap 装置有哪些的意思!

5.2 使用文件建置swap

如果是在实体分割槽无法支持的环境下,此时前一小节提到的 loop 装置建置方法就派的上用场啦!只是利用 dd 去建置一个大文件而已。

1. 使用 dd 这个命令来新增一个 128MB 的文件在 /tmp 底下:
[root@www ~]# dd if=/dev/zero of=/tmp/swap bs=1M count=128
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 1.7066 seconds, 78.6 MB/s

[root@www ~]# ll -h /tmp/swap
-rw-r--r-- 1 root root 128M Oct 28 15:33 /tmp/swap
2. 使用 mkswap 将 /tmp/swap 这个文件格式化为 swap 的文件格式:
[root@www ~]# mkswap /tmp/swap
Setting up swapspace version 1, size = 134213 kB
# 这个命令下达时请『特别小心』,因为下错字节控制,将可能使您的文件系统挂掉!
3. 使用 swapon 来将 /tmp/swap 启动啰!
[root@www ~]# free
             total       used       free     shared    buffers     cached
Mem:        742664     450860     291804          0      45584     261284
-/+ buffers/cache:     143992     598672
Swap:      1277088         96    1276992

[root@www ~]# swapon /tmp/swap
[root@www ~]# free
             total       used       free     shared    buffers     cached
Mem:        742664     450860     291804          0      45604     261284
-/+ buffers/cache:     143972     598692
Swap:      1408152         96    1408056

[root@www ~]# swapon -s
Filename                 Type            Size    Used    Priority
/dev/hdc5                partition       1020088 96      -1
/dev/hdc7                partition       257000  0       -2
/tmp/swap                file            131064  0       -3
4. 使用 swapoff 关掉 swap file
[root@www ~]# swapoff /tmp/swap
[root@www ~]# swapoff /dev/hdc7
[root@www ~]# free
             total       used       free     shared    buffers     cached
Mem:        742664     450860     291804          0      45660     261284
-/+ buffers/cache:     143916     598748
Swap:      1020088         96    1019992  <==回复成最原始的样子了!

5.3 swap使用上的限制

swap 在目前的壁纸计算机来讲,存在的意义已经不大了!如果是针对服务器或者是工作站这些常年上线的系统来说的话,那么,无论如何,swap 还是需要创建的。
因为 swap 主要的功能是当物理内存不够时,则某些在内存当中所占的程序会暂时被移动到 swap 当中,让物理内存可以被需要的程序来使用。另外,如果你的主机支持电源管理模式, 也就是说,你的 Linux 主机系统可以进入『休眠』模式的话,那么, 运行当中的程序状态则会被纪录到 swap 去,以作为『唤醒』主机的状态依据! 另外,有某些程序在运行时,本来就会利用 swap 的特性来存放一些数据段, 所以, swap 来是需要创建的!只是不需要太大!
不过, swap 在被创建时,是有限制的喔!
1. 核心 2.4.10 版本以后,单一 swap 量已经没有 2GB 的限制了,
2. 但是,最多还是仅能创建到 32 个 swap 的数量!
3. 而且,由于目前 x86_64 (64位) 最大内存寻址到 64GB, 因此, swap 总量最大也是仅能达 64GB 就是了!

posted @ 2015-03-21 17:48  ice-mj  阅读(450)  评论(0编辑  收藏  举报