04、Linux 基础 - 磁盘与文件系统管理

认识Linux文件系统:

整块磁盘的组成主要有:

1、 圆形的碟片(主要记录数据);
2、 机械手臂,与在机械手臂上的磁头(擦写碟片上的数据);
3、 主轴马达,可以转动碟片,让机械手臂的磁头在碟片上读写数据;

碟片上的物理组成又是:

  • 扇区(Sector)为最小的物理存储单位,且依据磁盘设计的不同,目前主要有512B与4KB两种格式
  • 将扇区组成一个圆,那就是柱面(Cylinder)
  • 早期的分区主要以柱面为最小分区单位,现在的分区通常使用扇区为最小分区单位(每个扇区都有其号码)
  • 磁盘分区表主要有两种格式,MBR(限制较多)、GPT
  • MBR分区表中,第一个扇区最重要,里面有:主引导记录(Master boot record,MBR)——446B、分区表——64B。
  • GPT分区表除了分区数量扩充较多之外,支持的磁盘容量也可以超过2TB

文件系统特性:

磁盘分区完毕后要进行格式化,这是因为每种操作系统所设置的文件属性/权限不同,为了存放这些文件所需的数据,因此就需要将分区进行格式化,以成为操作系统能够利用的文件系统格式

在Linux的学习中,我们通常称呼一个可被挂载的数据为一个文件系统而不是一个分区

我们知道,每个文件除了自身的数据还有非常多的属性,,例如文件的权限(rwx)和文件属性等,文件系统通常会将这两部分的数据分别存放在不同的区块,权限与属性放置到inode中,至于实际数据则放到数据区块中,另外,还有一个超级区块。

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

这种数据存储的方式我们称为索引式文件系统

与之对比的文件系统比如U盘的FAT格式,读取了一个区块,才能知道下一个区块的位置,如此往复(所以常常需要碎片整理:同一个文件所属的区块集合在一起,使读取容易)

Linux的ext2文件系统(inode):

标准的ext2就是使用这种inode为基础的Linux文件系统

文件系统一开始就将inode与数据区块规划好了,除非重新格式化(或利用resize2fs等命令修改大小),否则inode与数据区块固定后就不再变动。

但是,当我们文件系统高达数百GB时,所有的inode与数据区块通通放在一起就不太合适了,因此,ext2文件系统格式化的时候基本上时区分为多个区块群组(block group),每个区块群组都有独立的inode、数据区块、超级区块系统。文件系统最前面有一个启动扇区(boot sector),这个启动扇区可以安装启动引导程序(这样才能够制作出多重引导环境)

每一个区块群组的内容如下:

数据区块(data block):

ext2文件系统中所支持的区块大小由1k、2k、4k(在格式化时各个区块的大小就固定了)

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

虽然ext2已经能够支持大于2GB以上的单一文件容量,不过某些应用程序依旧使用旧的限制

另外的基本限制如下:

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

inode表(inode table):

inode会记录如下数据:

  • 该文件的读写属性(read、write、excute)
  • 该文件的拥有者与用户组(owner、group)
  • 该文件的大小
  • 改文件建立时间或状态改变的时间(ctime)
  • 最近一次读取的时间(atime)
  • 最近修改的时间(mtime)
  • 定义文件特性的标识(flag),如SetUID
  • 该文件真正内容的指向(pointer)

inode的数量与大小也是在格式化的时候就固定了,inode还有什么特色?

  • 每个inode大小均固定为128B(新的ext4与xfs可设置到256B)
  • 每个文件都仅会占用一个inode而已
  • 文件系统能够建立的文件数量与inode有关
  • 系统读取文件时需要先找到inode,并分析inode所记录的权限与用户是否符合,然后(符合)再读取区块内容

这个CSDN找到了鸟哥的这样一张图

 

上图最左边为inode本身(128bytes),里面有12个直接指向block号码的对照,这12组记录就能够直接读取block号码啦!至于所谓的间接就是再拿一个block来当作记录block号码的记录区,如过档案太大的时候,就会使用间接的block来记录编号。如上图当中间接只是拿一个block来记录额外的号码而已。同理,如果档案持续增大,那么就会利用所谓的双间接,第一个block仅指出下一个记录编号的block在那里,实际记录的在第二个block当中。

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

12个直接指向:12*1K=12K
间接:256*1K = 256K;
双间接: 256*256*1K;
三间接:256*256*256*1K;
总额: 12+256+256*256+256*256*256 = 16G;

故区块格式化为1k大小时,可以容纳的最大文件为16GB

超级区块(Superblock):

超级区块是记录整个文件系统相关的地方,没有超级区块,就没有整个文件系统,它主要记录的信息有:

  • 数据区块与inode的总量
  • 未使用和已经使用的inode与数据区块、数量
  • 数据区块与inode的大小(block为1、2、4k,inode为128B或256B)
  • 文件系统的挂载时间、最近一次写入数据的时间、最近一次检验磁盘(fsck)的时间等文件系统的相关信息
  • 一个有效位数值,若此文件系统已被记载,则有效位为0,若未被挂载,则有效位为1

如果超级区块损坏,你的文件系统可能就需要花费很多时间去恢复,一般来说,超级区块的大小为1024B。此外,每个区块群组都可能还要超级区块。但是我们说一个文件系统应该仅有一个超级区块而已,那这是怎么回事?事实上除了第一个区块群组内会含有超级区块外,后续的区块群组不一定含有超级区块,而若含有超级区块则该超级区块主要是作为第一个区块群组内超级区块的备份,这样可以进行超级区块的恢复

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

这个区块可以描述每个区块群组的开始与结束的区块,以及说明每个区段(超级区块、对照表、inode对照表、数据区块)分别介于哪一个区块之间,这部分也能够用dumpe2fs来观察

区块对照表(block bitmap):

新增文件时总会用到区块,那你要使用哪个区块来做记录?当然是选择空区块来记录新文件的数据,那你怎么知道哪个区块是空的?这就要通过区块对照表的辅助了。从区块对照表当中可以知道哪些区块是空的,因此我们的系统就能够很快速地找到可使用的空间来处理文件。

inode对照表(inode bitmap):

这个其实与区块对照表的功能类似,只是区块对照表记录的是使用与未使用的区块号码,inode对照表则是记录使用与未使用的inode号码。

dumpe2fs(查询ext系列超级区块):

使用dumpe2fs可以查询ext系列文件系统的超级区块信息(仅对ext文件系统有效)

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

利用 blkid 这个命令可以显示出目前系统被格式化的设备,后面的TYPE就可以看出文件系统类型。

[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 的号码有关就是了!很重要!

与目录树的关系:

目录:

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

如果想要实际观察root根目录内的文件所占用的inode号码时,可以使用ls -i这个选项来处理:

最左边就是inode号码

文件:

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

目录树读取:

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

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

[root@study ~]# ll -di / /etc /etc/passwd
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /
33595521 drwxr-xr-x. 131 root root 8192 Jun 17 00:20 /etc
36628004 -rw-r--r--. 1 root root 2092 Jun 17 00:20 /etc/passwd

该文件的读取流程为(假设读取者身份为 dmtsai 这个一般身份使用者):

1、 /的inode:通过挂载点的信息找到inode号码为128的根目录inode,且inode规范的权限让我们可以读取该block的内容(有r与x);
2、 /的block:经过上个步骤取得block的号码,并找到该内容有etc/目录的inode号码(33595521);
3、 etc/的inode:读取33595521号inode得知dmtsai具有r与x的权限,因此可以读取etc/的block内容;
4、 etc/的block:经过上个步骤取得block号码,并找到该内容有passwd文件的inode号码(36628004);
5、 passwd的inode:读取36628004号inode得知dmtsai具有r的权限,因此可以读取passwd的block内容;
6、 passwd的block:最后将该block内容的数据读出来;

文件系统大小与磁盘读取性能:

关于文件系统的使用效率上,当你的一个文件系统规划的很大时,例如 100GB 这么大时, 由于磁盘上面的数据总是来来去去的,所以,整个文件系统上面的文件通常无法连续写在一起(区块号码不会连续的意思),
而是填入式的将数据填入没有被使用的区块当中。如果文件写入的区块真的分的很散, 此时就会有所谓的文件数据离散的问题发生了。

虽然我们的 ext2 在 inode 处已经将该文件所记录的区块号码都记上了, 所以数据可以一次性读取,但是如果文件真的太过离散,确实还是会发生读取效率低落的问题。 因为磁头还是得要在整个文件系统中来来去去的频繁读取。果真如此,那么可以将整个文件系统内的数据全部复制出来,将该文件系统重新格式化, 再将数据给他复制回去即可解决这个问题。

此外,如果文件系统真的太大了,那么当一个文件分别记录在这个文件系统的最前面与最后面的区块号码中, 此时会造成磁盘的机械手臂移动幅度过大,也会造成数据读取性能的低落。而且磁头在搜寻整个文件系统时,
也会花费比较多的时间去搜寻!因此,磁盘分区的规划并不是越大越好,而是真的要针对你的主机用途来进行规划才行。

ext2/3/4文件的存取与日志式文件系统的功能:

假如我们想要新增一个文件,此时文件系统的操作是:

1、 先确定用户对于欲新增文件的目录是否具有w与x权限,若有才能继续;
2、 根据inode对照表找到没有使用的inode号码,并将新文件的权限/属性写入;
3、 根据区块对照表找到没有使用中的block号码,并将实际的数据写入block中,且更新inode的block指向数据;
4、 将刚刚写入的inode与block数据同步更新inode对照表与区块对照表,并更新超级区块的内容;

一般来说,我们将 inode对照表与数据区块称为数据存放区域,至于其他例如超级区块、区块对照表与inode对照表等区段就被称为 metadata (元数据),因为他们经常变动。

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

为了解决这个问题,出现了日志式文件系统。

日志式文件系统:

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

万一数据的纪录过程当中发生了问题,那么我们的系统只要去检查日志记录区块, 就可以知道哪个文件发生了问题,针对该问题来做一致性的检查即可,而不必针对整块文件系统去检查。

Linux文件系统的运行:

我们知道,所有的数据都得要载入到内存后 CPU 才能够对该数据进行处理。如果你常常编辑一个好大的文件,在编辑的过程中又频繁的要系统来写入到磁盘中,由于磁盘写入的速度要比内存慢很多,因此你会常常耗在等待磁盘的写入/读取上。

为了解决这个效率的问题,inux 使用的方式是通过一个称为非同步处理(asynchronously) 的方式。所谓的非同步处理是这样的:

当系统载入一个文件到内存后,如果该文件没有被更动过,则在内存区段的文件数据会被设置为干净(clean)的。 但如果内存中的文件数据被更改过了(例如你用 nano 去编辑过这个文件),此时该内存中的数据会被设置为脏的 (Dirty)。此时所有的动作都还在内存中执行,并没有写入到磁盘中! 系统会不定时的将内存中设置为“Dirty”的数据写回磁盘,以保持磁盘与内存数据的一致性。

Linux 系统文件系统与内存有非常大的关系:

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

挂载点的意义:

将文件系统与目录树结合的动作我们称为“挂载”。挂载点一定是目录,该目录为进入该文件系统的入口。 因此并不是你有任何文件系统都能使用,必须要“挂载”到目录树的某个目录后,
才能够使用该文件系统的。

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

Linux还支持其他的文件格式:

  • 传统文件系统:ext2 / minix / MS-DOS / FAT (用 vfat 模块) / iso9660 (光盘)等等;
  • 日志式文件系统: ext3 /ext4 / ReiserFS / Windows’ NTFS / IBM’s JFS / SGI’s XFS / ZFS
  • 网络文件系统: NFS / SMBFS

Linux VFS:

Linux系统都是通过一个叫Virtual Filesystem Switch的内核功能区读取文件系统,也就是说,整个Linux识别的文件系统其实都是VFS在进行管理,我们用户并不需要知道每个硬盘设备分区上面的文件系统是什么,VFS会主动帮助我们做好读取的工作

XFS文件系统简介:

CentOS 7开始,默认的文件系统已经由原本的ext4变成了xfs文件系统,原因:

ext系列当前较烧脑筋的地方:支持度最广,但格式化最慢

ext文件系统对于文件格式化的处理方面,采用的是预先规划出所有的 inode、区块、元数据 等数据,未来系统可以直接取用,不需要再进行动态配置的作法。这个作法在早期磁盘容
量还不大的时候还算 OK,但时至今日,磁盘容量越来越大,连传统的 MBR 都已经被 GPT 所取代,现在都已经说到 PB 或 EB 以上容量了!可以想像,当你的 TB 以上等级的传统 ext 文件系统在格式化的时候,光是系统要预先分配 inode 与 区块就消耗你好多好多的时间。

XFS文件系统的配置:

xfs文件系统在数据的分布上,主要规划为三个部份,一个数据区 (data section)、一个文件系统活动登录区 (log section)以及一个实时运行区 (realtime section)。

  • 数据区(data section)

数据区就跟我们之前谈到的 ext 家族一样,包括 inode、数据区块、超级区块等数据,都放置在这个区块。这个数据区与 ext 家族的区块群组类似,
也是分为多个储存区群组(allocation groups)来分别放置文件系统所需要的数据。 每个储存区群组都包含了

1、 整个文件系统的超级区块;
2、 剩余空间的管理机制;
3、 inode的分配与追踪;

此外,inode与 block 都是系统需要用到时, 这才动态配置产生,所以格式化动作超级快。

  • 文件系统活动登录区(log section)

这个区域主要用来记录文件系统的变化,有点像是日志区。文件的变化会在这里记录下来,直到该变化完整地写入到数据区后,该条记录才会被结束。另外,xfs的设计很有趣,你可以指定外部的磁盘来作为xfs文件系统的日志区块。

  • 实时运行区(realtime section)

当文件要被创建时,xfs 会在这个区段找到一个到数个 extent 区块,将文件放置在这个区块,等到分配完毕后,再写入到 data section 的inode 和区块中。
这个extent 区块的大小得要在格式化的时候就先指定,最小值是 4K 最大可到 1G。一般非磁盘阵列的磁盘默认为64K的容量,而具有类似磁盘阵列的stripe情况下,则建议将extent设置为与stripe一样大,这个extent最好不要乱动,因为可能会影响物理磁盘的性能

XFS文件系统的描述数据观察:

有一个命令类似ext的系列的dumpe2fs观察xfs文件系统

xfs_info  挂载点|设备文件名

 

  • 第一行里面的isize:指的是inode的容量,每个有512B,agcount是存储区群组个数(allocation group),每个存储区群组有agsize个区块
  • 第二行里面的sectsz指的是逻辑扇区(sector)的容量设置为512B这么大的意思
  • 第四行里面的bsize指的是区块的容量,每个区块为4K的意思,共有blocks个区块在文件系统内
  • 第七行里面的internal指的是这个登录区的位置在文件系统内,而不是外部设备的意思


文件系统的简单操作:

磁盘与目录的容量:

磁盘的整体数据是在超级区块中,但是每个文件的容量则在inode当中记载,下面的命令叫我们方便查看:

df:

列出文件系统的整体磁盘使用量

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

 

  • Filesystem:代表该文件系统是在哪个硬盘分区,所以列出设备名称
  • 1K-blocks:说明下面的数字单位是1KB,可以用-h或-m来改变容量
  • Used:使用掉的磁盘空间
  • Available:剩下的磁盘空间大小
  • Use%:磁盘使用率
  • Mounted on:就是磁盘的挂载目录(挂载点)

/proc的东西都是Linux系统所需要加载的系统数据,而且是挂载在内存中的。

/dev/shm/,其实是利用内存虚拟出来的磁盘空间,通常是总物理内存的一半

du:

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

容量默认以kb为单位

硬链接与符号链接-ln:

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

想要读取一个文件,必须经过目录记录的文件名来指向到正确的inode号码才能读取,也就是说,其实文件名只与目录有关,但是文件内容则与inode有关。硬链接就是在某个目录下新增一条文件名链接到某inode号码的关联记录而已。

 

如图,两个文件的inode都是17678412,也就是说访问这两个文件访问的是一个地方。

硬链接有这样的性质:

  • 不能跨文件系统
  • 不能跨链接目录

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

符号链接就是建立一个独立的文件,这个文件会让数据的读取指向它链接的那个文件的文件名。

只是指向操作,当源文件被删除,符号链接的文件就打不开了

 

链接文件的重要内容就是它会写上目标文件的文件名

由符号链接创建的文件为一个独立的新文件,所以会占用inode与区块

使用ln命令去制作链接文件:

ln [-sf] 源文件 目标文件
-s:如果不加任何参数就进行链接,就是硬链接,至于-s就是符号链接
-f:如果目标文件存在时,就主动的将目标文件直接删除后再建立

磁盘的分区、格式化、检验与挂载:

如果我们想要在系统里面新增一块磁盘的话,应该做哪些操作:

1、 对磁盘进行划分,以建立可用的磁盘分区;
2、 对该磁盘分区进行格式化(format),以建立系统可用的文件系统;
3、 若想要仔细一点,则可对刚刚建立好的文件系统进行检验;
4、 在Linux系统上,需要建立挂载点(亦即是目录),并把它挂在上来;

观察磁盘分区状态:

liblk:

lsblk(可以看成是【list block device】的缩写):列出系统上所有的磁盘列表

lsblk [-dfimpt] [device]
选项与参数:
-d  :仅列出磁盘本身,并不会列出该磁盘的分区数据
-f  :同时列出该磁盘内的文件系统名称
-i  :使用 ASCII 的线段输出,不要使用复杂的编码 (再某些环境下很有用)
-m  :同时输出该设备在 /dev 下面的权限数据 (rwx 的数据)
-p  :列出该设备的完整文件名!而不是仅列出最后的名字而已。
-t  :列出该磁盘设备的详细数据,包括磁盘阵列机制、预读写的数据量大小等

[root@study ~]# lsblk
NAME               MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sr0                  11:0    1 1024M  0 rom
vda                   8:0    0  200G  0 disk  
├─vda1                8:1    0    2G  0 part /boot
├─vda2                8:2    0   58G  0 part
│ ├─rhel-root       253:0    0  191G  0 lvm  /
│ └─rhel-swap       253:1    0    6G  0 lvm
└─vda3                8:3    0  140G  0 part
  └─rhel-root       253:0    0  191G  0 lvm  /

从上面的输出我们可以很清楚的看到,目前的系统主要有个 sr0 以及一个 vda 的设备,而 vda 的设备下面又有三个分区, 其中 vda3 甚至还有因为 LVM 而产生的文件系统。

输出的信息有:

  • NAME:就是设备的文件名,会省略/dev等前导目录!
  • MAJ:MIN:其实核心识别的设备都是通过这两个代码来熟悉的!分别是主要:次要设备代码!
  • RM:是否为可卸载设备 (removable device),如光盘、USB 磁盘等等
  • SIZE:容量
  • RO:是否为只读设备的意思
  • TYPE:是磁盘 (disk)、分区 (partition) 还是只读存储器 (rom) 等输出
  • MOUTPOINT:挂载点

blkid:

列出设备的 UUID(universally unique identifier) 等参数

UUID是全局唯一表示符,是Linux给与设备的独一无二的标识符,这个标识符就可以拿来挂载或是使用这个设备或文件系统

parted:

parted:列出磁盘的分区表类型与分区信息

parted device_name print

 

Model:磁盘的模块名称(厂商)
Disk:磁盘总容量
Sector size (logical/physical):磁盘的每个逻辑/物理扇区容量
Partition:分区表格式

磁盘分区:gdisk/fdisk:

磁盘分区要注意的是:MBR分区表请使用fdisk分区,GPT请使用gdisk分区,这个搞错会导致分区失败。

gdisk:

gdisk 设备名称

 

d:删除一个分区
n:增加一个分区
p:打印出分区表
q:不保存分区直接离开gdisk
w:保存分区操作后离开gdisk

你可以随便玩gdisk,只要最后按q离开就不会生效

 

现在分区主要以扇区为最小单位

上面的各项的意义是:

  • Number:分区编号,1号指的就是/dev/sda1这样计算
  • Start:每一个分区的开始扇区号码位置
  • End:每一个分区的结束扇区号码位置,与start之间可以算出分区的总容量
  • Size:就是分区的容量
  • Code:在分区内的可能的文件系统类型,Linux为8300,swap为8200,这只是个提示
  • Name:文件系统的名称等

从上表我们可以发现:

  • 整个磁盘还可以进行额外的划分,因为最大扇区为83886080,但只用到65026047号而已
  • 分区的设计中,新分区通常选用上一个分区的结束扇区号码加1作为起始扇区号码

另外注意:

  • 这个gdisk命令只有root可以执行
  • 使用的设备文件名请不要加上数字,因为磁盘分区是针对整个磁盘设备而不是某个分区(不能用/dev/sda1,要用磁盘/dev/sda)

♦新增分区示例操作:

我们要来做如下分区:

  • 1GB的xfs文件系统(Linux)
  • 1GB的vfat文件系统(Windows)
  • 0.5GB的swap(Linux swap) (这个分区等一下会被删除)

 

在Last sector中绝对不要回车,否则就是把磁盘剩余所有扇区都使用了,这个我们仅要1G(输入+1G系统会自动计算最接近你需要容量的扇区号码)

按照上面的方法分出所需要求,最后就是这样:

 

很nice,文件系统的ID一般来说,Linux大概就是8200、8300、8e00等三种格式,Windows几乎都用0700

最后我们按w写入新的分区,会出现警告,这是因为这块磁盘现在正在使用中,因此系统无法立即加载新的分区表

 

可以看到,还没有sda4、sda5、sda6

这时我们可以通过两种方式来处理,一种是重新启动,一种是通过partprobe这个命令来处理

partprobe:更新Linux内核信息

partprobe [-s]  
//不加-s,那屏幕不显示信息

 

接下来我们来删除分区,删除sda6(Linux swap)

这个删除很简单,直接gdisk /dev/sda后,输入d,然后输入6,,最后w写入即可,别忘了出来之后用partprobe更新内核信息,然后lsblk一看,就会发现sda6消失了

千万不要去处理正在使用中的分区

磁盘格式化(创建文件系统):

分区完毕后自然就是去进行文件系统的格式化。格式化的命令非常简单,那就是【make filesystem,mkfs】这个命令。这个命令是个综合命令,他会去调用正确的文件系统格式化工具软件。

“格式化”其实应该称为“创建文件系统 (make filesystem)”才对,所以使用的指令是 mkfs

创建的 xfs 文件系统-mkfs.xfs:

mkfs.xfs [-b bsize] [-d parms] [-i parms] [-l parms] [-L label] [-f] \
                         [-r parms] 设备名称
选项与参数:
关于单位:下面只要谈到“数值”时,没有加单位则为 Bytes 值,
        可以用 k,m,g,t,p (小写)等来解释
        比较特殊的是 s 这个单位,它指的是 sector 的“个数”喔!
-b  :后面接的是区块量,可由 512 到 64k,不过最大容量限制为 Linux 的 4k 喔!
-d  :后面接的是重要的 data section 的相关参数值,主要的值有:
      agcount=数值  :设置需要几个储存群组的意思(AG),通常与 CPU 有关
      agsize=数值   :每个 AG 设置为多少容量的意思,通常 agcount/agsize
                    只选一个设置即可
      file          :指的是“格式化的设备是个文件而不是个设备”的意思!
                    (例如虚拟磁盘)
      size=数值     :data section 的容量,亦即你可以不将全部的设备容
                    量用完的意思
      su=数值       :当有 RAID 时,那个stripe数值的意思,与下面的 w搭配使用
      sw=数值       :当有 RAID 时,用于储存数据的磁盘数量(须扣除备份碟与备用碟)
      sunit=数值    :与su相当,不过单位使用的是“几个sector(512Bytes大小)”的意思
      swidth=数值   :就是 su*sw 的数值,但是以“几个 sector(512Bytes大小)”来设置
-f  :如果设备内已经有文件系统,则需要使用这个 -f 来强制格式化才行!
-i  :与 inode 有较相关的设置,主要的设置值有:
      size=数值     :最小是 256Bytes 最大是 2k,一般保留 256 就足够使用了!
      internal=[0|1]:log 设备是否为内置?默认为 1 内置,如果要用外部设备
                    ,使用下面设置
      logdev=device :log 设备为后面接的那个设备上面的意思,
                     需设置 internal=0 才可!
      size=数值     :指定这块登录区的容量,
                    通常最小得要有 512 个 block,大约 2M 以上才行!
-L  :后面接这个文件系统的标头名称Label name的意思!
-r  :指定realtime section的相关设置值,常见的有:
      extsize=数值  :就是那个重要的 extent 数值,一般不须设置,但有 RAID 时,
                      最好设置与 swidth 的数值相同较佳!最小为 4K 最大为 1G 。

没有特殊需求的话,直接mkfs.xfs /dev/sda4即可,非常快就会创建一个 xfs文件系统

XFS 文件系统 for RAID 性能优化 (Optional):

磁盘阵列是多颗磁盘组成一颗大磁盘的意思, 利用同步写入到这些磁盘的技术,不但可以加快读写速度,还可以让某一颗磁盘坏掉时,整个文件系统还是可以持续运行的状态!那就是所谓的容错。

基本上,磁盘阵列 (RAID) 就是通过将文件先细分为数个小型的分区区块 (stripe) 之后,然后将众多的 stripes 分别放到磁盘阵列里面的所有磁盘, 所以一个文件是被同时写入到多个磁盘去,当然性能会好一些。为了文件的保全性,所以在这些磁盘里面,会保留数个(与磁盘阵列的规划有关) 备份磁盘 (parity disk), 以及可能会保留一个以上的备用磁盘(spare disk),这些区块基本上会占用掉磁盘阵列的总容量,不过对于数据的保全会比较有保障!

那个分区区块 stripe 的数值大多介于 4K 到 1M 之间,这与你的磁盘阵列卡支持的项目有关。stripe 与你的文件数据容量以及性能相关性较高。 当你的系统大多是大型文件时,一般建议stripe 可以设置大一些,这样磁盘阵列读/写的频率会降低,性能会提升。如果是用于系统,那么小文件比较多的情况下, stripe 建议大约在 64K 左右可能会有较佳的性能。不过,还是都须要经过测试啦!完全是 case by case 的情况。

文件系统的读写要能够有最优化,最好能够搭配磁盘阵列的参数来设计,这样性能才能够起来!也就是说,你可以先在文件系统就将 stripe 规划好, 那交给 RAID 去存取时,它就无须重复进行文件的 stripe 过程,性能当然会更好!那格式化时,最优化性能与什么咚咚有关呢?我们来假设个环境好了:

我有两个线程的 CPU 数量,所以 agcount 最好指定为 2

当初设置 RAID 的 stripe 指定为 256K 这么大,因此 su 最好设置为 256k

设置的磁盘阵列有 8 颗,因为是 RAID5 的设置,所以有一个 parity (备份碟),因此指定 sw 为 7

由上述的数据中,我们可以发现数据宽度 (swidth) 应该就是 256K*7 得到 1792K,可以指定 extsize 为 1792k

ext4文件系统mkfs.ext4:

如果想要格式化为ext4的传统Linux文件系统的话,可以使用如下:

mkfs.ext4 [-b size] [-L label] 设备名称
选项与参数:
-b  :设置 block 的大小,有 1K, 2K, 4K 的容量,
-L  :后面接这个设备的标头名称。

其他文件系统mkfs:

mkfs其实是个综合命令,使用mkfs -t xfs时,他就会去找mkfs.xfs的相关参数给我们使用。如果想要知道系统还支持哪种文件系统的格式化功能,输入mkfs再按两次Tab即可

文件系统检验:

xfs_repair处理XFS文件系统

xfs_repair [-fnd] 设备名称
-f:后面的设备其实是个文件而不是实体设备
-n:单纯检查并不修改文件系统的任何数据
-d:通常用在单人维护模式下面,针对根目录(/)
   进行检查与修复的操作,很危险,不要随便用

xfs_repair可以检查/修复文件系统,不过,因为修复文件系统是个庞大的任务,因此,修复时该文件系统不能被挂载。所以,检查与修复/dev/sda4没啥问题,但是修复已被挂载的文件系统时,就会出现问题,卸载后再处理即可。

而根目录无法被卸载,那根目录有问题怎么办?进入单人维护模式,加入d参数即可

fsck.ext4处理ext4文件系统

fsck是个综合命令,针对而ext4的话,用fsck.ext4处理即可

fsck.ext4 [-pf] [-b 超级区块] 设备名称
-p:当文件系统在修复时,若要回复Y的操作时,自动回复Y
-f:强制检查,一般来说,如果fsck没有发现任何unclean的标识,
   不会主动进入详细检查的,若您想要强制fsck详细检查,就要-f
-D:针对文件系统下的目录进行最佳化配置
-b:后面接超级区块的位置,一般这个选项用不到,但是若果你
    的超级区块做损坏时,通过这个参数即可利用文件系统内备
    份的超级区块来尝试恢复,一般来说,超级区块备份在如下:
    1K区块放在8193,2K区块放在16384,4K区块放在32768

我们可以利用dumpe2fs -h /dev/sda5找到Blocks per group的信息,即可知道超级区块的位置,比如是32768,然后fsck.ext4 -b 32768 /dev/sda5即可检查文件系统超级区块问题

注意,通常只有root且你的文件系统有问题的时候才使用此命令,否则正常情况下使用此命令,可能会造成对系统的危害。

被检查的硬盘分区务必是卸载状态

文件系统的挂载与卸载:

每次进行挂载前,要确定几件事情:

  • 单一文件系统不应该被重复挂载在不同的挂载点(目录)上
  • 单一目录不应该重复挂载多个文件系统
  • 要作为挂载点的目录,理论上应该是空目录才行

如果你要挂载的目录里面并不是空的,那么挂载了文件系统之后,原目录下的东西就会暂时消失
(卸载后才会再次现身)

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

centOS现在的版本基本上不需要-t,系统会自动分析最恰当的文件系统来尝试挂载你需要的设备,系统的一句就是分析超级区块搭配Linux自己的驱动程序去测试挂载,测试成功,就立刻自动使用该类型的文件系统挂载起来。

  • /etc/filesystems:系统指定的测试挂载文件系统类型的优先级
  • /proc/filesystems:Linux系统已经加载的文件系统类型

Linux支持的文件系统驱动程序写在如下目录:

  • /lib/modules/$ (uname -r) /kernel/fs/

例如ext4的驱动程序就写在【/lib/modules/$ (uname -r) /kernel/ext4/】目录下

挂载 xfs/ext4/vfat 等文件系统:

 

挂载CD或DVD光盘:

 

光盘一挂载之后就无法退出光盘了,除非你将它卸载才能够退出

尽量使用UUID去进行挂载,因为它一般不会变动,而一块磁盘到了别人的电脑就可能不是sda这个名字了

因为是光盘,所以磁盘使用率达到了100%,所以你无法直接写入任何数据到光盘中。

此外,如果你使用的是图形界面,那么系统会自动帮你挂载这个光盘到/media目录。也可以不卸载就直接退出(但是命令行不能这样

挂载vfat中文移动磁盘(USB磁盘):

我们来挂载vfat格式的磁盘

mount -o codepage=950,iocharset=utf8 UUID="35BC-6D6B"  /data/usb

因为是中文文件名的数据,那么可以在挂载时指定挂载文件系统的所使用的的语系。在man mount找到vfat文件格式当中可以使用codepage来处理,中文语系的代码是950,另外,如果想要指定中文是Unicode还是Big5,就要指定iocharset二选一了。

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

整个目录树最重要的地方就是根目录,根目录不可能被卸载,如果你的挂载参数要改变或是根目录出现【只读】状态,如何重新挂载,最可能的处理方式就是重新启动(reboot),不过你也可以这样:

#将/重新挂载,并加入参数为rw与auto
mount -o remount,rw,auto /

重点是那个-o remountde,xx的选项与参数。要重新挂载时,这是个非常重要的机制。尤其是当你进入单人维护模式下的时候,你的根目录常会被系统挂载为只读。

另外,我们也可以利用mount来将某个目录挂载到另外一个目录。这并不是挂载文件系统,而是额外挂载某个目录的方法。虽然下面的方法也可以用符号链接来实现,不过某些不支持符号链接的程序运行中,就用到这个方法了

 

两个目录链接在同一个inode,这就是mount --bind的功能,所以从此进入/data/var也就是进入/var

umount(将设备文件卸载):

-umount [-fn] 设备文件名或挂载点
-f:强制卸载,可用在类似网络系统(NFS)无法读取到的情况下
-l:立刻卸载文件系统,比-f还强
-n:不更新/etc/mtab情况下卸载

就是直接将已经挂载的文件系统卸载,卸载之后,可以使用df或mount看看是否还存在于目录中。卸载的方式,可以输入设备文件名或挂载点,都行。

 

卸载的基本原则就是那块磁盘不是正在被使用,你在那个磁盘目录下,就不能卸载它,除非你离开目录

 

磁盘/文件系统参数自定义:

mknod:

Linux里万物皆文件,那么文件是如何代表设备的,就是靠major(主要)和minor(次要)数值来替代

 

上面的8就是主要设备代码(major),而0~5就是次要设备代码(minor)。我们的Linux内核支持的设备文件数据就是通过这两个数值来决定的。

一般我们不需要手动建立设备文件。不过某些情况下面我们可能还是要手动处理设备文件,例如在某些服务被chroot到特定目录下时,就需要这样做了

mknod 设备文件名 [bcp] [Major] [Minor]
b:设置设备名称成为一个外接存储设备文件,例如磁盘等
c:设置设备名称成为一个外接输入设备文件,例如鼠标等
p:设置设备名称成为一个FIFO文件
Major:主要设备码
Minor:次要设备码

xfs_admin修改XFS文件系统的UUID与Label name:

如果你当初格式化的时候忘记加入了标头名称,后来想再加入,无需格式化,直接使用xfs_admin即可,它还可以设置UUID

该命令只对xfs文件系统类型有效

xfs_admin [-lu] [-L label] [-U uuid] 设备名
-l:列出这个设备的label name
-u:列出这个设备的UUID
-L:设置这个设备的Label name
-U:设置这个设备的UUID

 

tune2fs修改ext4的label name与UUID

tune2fs [-l] [-L Label] [-U uuid] 设备文件名
-l:类似dumpe2fs,将superblock内的数据读出来
-L:修改Label name
-U:修改UUID

设置启动挂载(fstab与mtab):

可不可以在启动时就将我要的文件系统挂载好呢?这样我就不用每次进入Linux都要挂载一次。当然可以,直接到/etc/fstab里面去修改就行,不过,系统挂载有一些限制:

  • 根目录/是必须挂载的,而且一定要先于其他挂载点被挂载进来
  • 其他挂载点必须为已建立的目录,可任意指定,但一定要遵循必须得系统目录架构原则(FHS)
  • 所有挂载点在同一时间内,只能挂载一次
  • 所有的硬盘在同一时间内,只能挂载一次
  • 如若进行卸载,您必须将工作目录转移到挂载点之外

 

下面那6个字段分别是

[设备/UUID等]    [挂载点]   [文件系统]  [文件系统参数]  [dump]  [fsck]

设备/UUID等:

这个字段可以填写的数据主要有三个项目:

  • 文件系统或磁盘的设备文件名,如/dev/sda2等
  • 文件系统的UUID名称(UUID=?)
  • 文件系统的LABEL名称(LABEL=?)

自己编写的时候写哪个都行

挂载点:

一定是目录

磁盘分区的文件系统:

在手动挂载时可以让系统自动测试挂载,但在这个文件当中我们必须要手动写入文件系统才行,包括:xfs、ext4、fab、reiserf、nfs等

文件系统参数:

mount那里的那一帮子

参数 内容意义
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 来取消这个功能!
defaults 同时具有 rw, suid, dev, exec, auto, nouser, async 等参数。 基本上,默认情况使用 defaults 配置即可!

能否被dump备份使用:

dump是一个用来做备份的命令,不过现在有太多备份方案,这个项目可以不用理会,填0就好

是否以fsck检验扇区

早期启动流程中,会有一段时间去检验本机的文件系统,看看文件系统是否完整(clean),不过这个阶段主要是通过fsck去完成,我们现在用的xfs文件系统就没有办法适用,因为xfs会自己自行检验,填0即可

/etc/fstab是启动时的配置文件,不过,实际文件系统的挂载是记录到 /etc/mtab 和 /proc/mounts 这两个文件中的。每次我们在修改文件系统的挂载时,也会同时修改这两个文件。但是,万一发生你在/etc/fstab输入的数据有误,导致无法顺利启动成功,而进入单人模式中,那时候的/可是只读的状态,当然你无法修改/etc/fstab,也无法更新/etc/mtab,怎么办?没关系,可以用这招:

mount -n -o remount,rw /

特殊设备loop挂载(镜像文件不刻录就挂载使用)

如果有光盘镜像文件,或是使用文件作为磁盘的方式时,那就要使用特别的方法来将他挂载起来,不需要刻录

挂载CD/DVD镜像文件:

想像一下如果今天我们从中科大镜像站下载了 Linux 或者是其他所需CD/DVD的镜像文件后, 难道一定需要刻录成为光盘才能够使用该文件里面的数据吗?当然不是啦!我们可以通过 loop 设备来挂载的!

[root@study ~]# ll -h /tmp/CentOS-7.0-1406-x86_64-DVD.iso
-rw-r--r--. 1 root root 3.9G Jul 7 2014 /tmp/CentOS-7.0-1406-x86_64-DVD.iso
# 看到上面的结果吧!这个文件就是镜像文件,文件非常的大吧!
[root@study ~]# mkdir /data/centos_dvd
[root@study ~]# mount -o loop /tmp/CentOS-7.0-1406-x86_64-DVD.iso /data/centos_dvd
[root@study ~]# df /data/centos_dvd
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 4050860 4050860 0 100% /data/centos_dvd
# 就是这个项目! .iso 镜像文件内的所有数据可以在 /data/centos_dvd 看到!
[root@study ~]# ll /data/centos_dvd
total 607
-rw-r--r--. 1 500 502 14 Jul 5 2014 CentOS_BuildTag <==瞧!就是DVD的内容啊!
drwxr-xr-x. 3 500 502 2048 Jul 4 2014 EFI
-rw-r--r--. 1 500 502 611 Jul 5 2014 EULA
-rw-r--r--. 1 500 502 18009 Jul 5 2014 GPL
drwxr-xr-x. 3 500 502 2048 Jul 4 2014 images
.....(下面省略).....
[root@study ~]# umount /data/centos_dvd/
# 测试完成!记得将数据给他卸载!

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

建立大文件以制作loop设备文件:

想一想,既然能够挂载 DVD 的镜像文件,那么我能不能制作出一个大文件,然后将这个文件格式化后挂载呢? 好问题!这是个有趣的动作!而且还能够帮助我们解决很多系统的分区不良的情况呢!举例来说,如果当初在分区时, 你只有分区出一个根目录,假设你已经没有多余的容量可以进行额外的分区的!偏偏根目录的容量还很大! 此时你就能够制作出一个大文件,然后将这个文件挂载!如此一来感觉上你就多了一个分区啰!用途非常的广泛啦!

下面我们在 /srv 下创建一个 512MB 左右的大文件,然后将这个大文件格式化并且实际挂载来玩一玩!

  • 建立大型文件
[root@study ~]# dd if=/dev/zero of=/srv/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 的意思。所以 bs*count 就是这个文件的容量了!
[root@study ~]# ll -h /srv/loopdev
-rw-r--r--. 1 root root 512M Jun 25 19:46 /srv/loopdev

dd就好像在叠砖块一样,将 512 块,每块 1MB 的砖块堆叠成为一个大文件 (/srv/loopdev)!

 

  • 大型文件的格式化

默认xfs 不能够格式化文件的,所以要格式化文件得要加入特别的参数(-f:强制格式化)才行

[root@study ~]# mkfs.xfs -f /srv/loopdev
[root@study ~]# blkid /srv/loopdev
/srv/loopdev: UUID="7dd97bd2-4446-48fd-9d23-a8b03ffdd5ee" TYPE="xfs"

 

  • 挂载

利用mount的-o参数来挂载

[root@study ~]# mount -o loop UUID="7dd97bd2-4446-48fd-9d23-a8b03ffdd5ee" /mnt
[root@study ~]# df /mnt
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 520876 26372 494504 6% /mnt

 

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

比较特别的是,CentOS 7.x 越来越聪明了,现在你不需要下达 -o loop 这个选项与参数,它同样可以被系统挂上来! 连直接输入 blkid 都会列出这个文件内部的文件系统耶!相当有趣!不过,为了考虑向下兼容性,鸟哥还是建议你加上 loop 比较妥当喔! 现在,请将这个文件系统永远的自动挂载起来吧!

永久自动挂载:

[root@study ~]# nano /etc/fstab
/srv/loopdev /data/file xfs defaults**,loop** 0 0
# 毕竟系统大多仅查询 block device 去找出 UUID 而已,因此使用文件创建的 filesystem,
# 最好还是使用原本的文件名来处理,应该比较不容易出现错误讯息的!
[root@study ~]# umount /mnt
[root@study ~]# mkdir /data/file
[root@study ~]# mount -a
[root@study ~]# df /data/file
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop0 520876 26372 494504 6% /data/file

内存交换分区(swap)之创建:

我们知道 CPU 所读取的数据都来自于内存, 那当内存不足的时候,为了让后续的程序可以顺利的运行,因此在内存中暂不使用的程序与数据就会被挪到 swap 中了。 此时内存就会空出来给需要执行的程序载入。由于 swap 是用磁盘来暂时放置内存中的信息,所以用到 swap 时,你的主机磁盘灯就会开始闪个不停啊!

使用物理分区创建内存交换分区:

1、 分区:先使用gdisk在你的磁盘中分区出一个分区给系统作为swap由于Linux的gdisk默认会将分区的ID设置为Linux的文件系统,所以你可能还得要设置一下systemID就是了;

2、 格式化:利用创建swap格式的“mkswap设备文件名”就能够格式化该分区成为swap格式;

3、 使用:最后将该swap设备启动,方法为:“swapon设备文件名”;

4、 观察:最终通过free与swapon-s这个指令来观察一下内存的用量吧!;

首先我们用gdisk进行分区,Hex code写8200

 

w退出保存后,用lsblk可以看见我们的新分区

 

用mkswap 格式化该分区为swap格式

 

开始观察看看:

 

最后写入配置文件,因为是swap,所以没有挂载点

 

使用文件创建内存交换文件:

如果是在实体分区无法支持的环境下,此时前一小节提到的 loop 设备创建方法就派的上用场啦! 与实体分区不一样的,这个方法只是利用 dd 去创建一个大文件而已。多说无益,我们就再通过文件创建的方法创建一个 128 MB 的内存交换空间吧

用dd新增大文件

 

使用mkswap将/tmp/swap格式化为内存交换文件的文件格式

 

这个命令写错字符将可能导致您的文件系统挂掉

使用swapon来将/tmp/swap启动

 

接下来写入/etc/fstab,注意,这里是个大文件,系统仅会查询区块设备(block device)不会查询文件,所以千万不能用UUID,不然系统会查不到

 

接下来用swapoff /tmp/swap /dev/sda6 来关闭示范的两个swap分区,再用swapon -a全部开启,如果fstab设置无误,这些就全部开启

 

说实话,swap 在目前的桌面电脑来讲,存在的意义已经不大了!这是因为目前的 x86 主机所含的内存实在都太大了 (一般入门级至少也都有 4GB 了),所以,我们的 Linux 系统大概都用不到 swap 这个玩意儿的。不过, 如果是针对服务器或者是工作站这些常年上线的系统来说的话,那么,无论如何,swap 还是需要创建的。

因为swap 主要的功能是当实体内存不够时,则某些在内存当中所占的程序会暂时被移动到swap 当中,让实体内存可以被需要的程序来使用。另外,如果你的主机支持电源管理模式,也就是说,你的 Linux 主机系统可以进入“休眠”模式的话,那么, 运行当中的程序状态则会被纪录到 swap 去,以作为“唤醒”主机的状态依据! 另外,有某些程序在运行时,本来就会利用swap 的特性来存放一些数据段, 所以, swap 来是需要创建的!只是不需要太大!

文件系统的特殊观察与操作:

磁盘空间浪费问题:

我们在前面的 EXT2 data block 介绍中谈到了一个 block 只能放置一个文件, 因此太多小文件将会浪费非常多的磁盘容量。但你有没有注意到,整个文件系统中包括 superblock, inodetable 与其他中介数据等其实都会浪费磁盘容量喔!所以当我们在 /dev/vda4, /dev/vda5 创建起 xfs/ext4 文件系统时, 一挂载就立刻有很多容量被用掉了!

另外,不知道你有没有发现到,当你使用 ls -l 去查询某个目录下的数据时,第一行都会出现一个“total”的字样! 那是啥东西?其实那就是该目录下的所有数据所耗用的实际 block 数量 *block 大小的值。 我们可以通过 ll -s 来观察看看上述的意义:

[root@study ~]# ll -sh
total 12K
4.0K -rw-------. 1 root root 1.8K May 4 17:57 anaconda-ks.cfg
4.0K -rw-r--r--. 2 root root 451 Jun 10 2014 crontab
0 lrwxrwxrwx. 1 root root 12 Jun 23 22:31 crontab2 -> /etc/crontab
4.0K -rw-r--r--. 1 root root 1.9K May 4 18:01 initial-setup-ks.cfg
0 -rw-r--r--. 1 root root 0 Jun 16 01:11 test1
0 drwxr-xr-x. 2 root root 6 Jun 16 01:11 test2
0 -rw-rw-r--. 1 root root 0 Jun 16 01:12 test3
0 drwxrwxr-x. 2 root root 6 Jun 16 01:12 test4

从上面的特殊字体部分,那就是每个文件所使用掉 block 的容量!举例来说,那个 crontab 虽然仅有 451Bytes , 不过他却占用了整个 block (每个 block 为 4K),所以将所有的文件的所有的 block 加总就得到 12KBytes 那个数值了。 如果计算每个文件实际容量的加总结果,其实只有不到 5K 而已

利用GNU的parted进行分区操作:

虽然你可以使用 gdisk/fdisk 很快速的将你的分区切割妥当,不过 gdisk 主要针对 GPT 而fdisk 主要支持 MBR ,对 GPT 的支持还不够! 所以使用不同的分区时,得要先查询到正确的分区表才能用适合的指令,好麻烦!有没有同时支持的指令呢?有的!那就是 parted 。

[root@study ~]# parted [设备] [指令 [参数]]
新增分区:mkpart [primary|logical|Extended] [ext4|vfat|xfs] 开始 结束
显示分区:print
删除分区:rm [partition]
[root@study ~]# parted /dev/sda print
Model: Virtio Block Device (virtblk) <==磁盘接口与型号
Disk /dev/sda: 42.9GB             <==磁盘文件名与容量
Sector size (logical/physical): 512B/512B  <==每个扇区的大小
Partition Table: gpt <==是 GPT 还是 MBR 分区
Disk Flags: pmbr_boot
Number Start End Size File system Name Flags
1 1049kB 3146kB 2097kB bios_grub
2 3146kB 1077MB 1074MB xfs
3 1077MB 33.3GB 32.2GB lvm
4 33.3GB 34.4GB 1074MB xfs Linux filesystem
5 34.4GB 35.4GB 1074MB ext4 Microsoft basic data
6 35.4GB 36.0GB 537MB linux-swap(v1) Linux swap

上面是最简单的 parted 指令功能简介,你可以使用“ man parted ”,或者是“ parted /dev/sda help mkpart ”去查询更详细的数据。比较有趣的地方在于分区表的输出。我们将上述的分区表示意拆成六部分来说明:

1、 Number:这个就是分区的号码啦!举例来说,1号代表的是/dev/sda1的意思;
2、 Start:分区的起始位置在这颗磁盘的多少MB处?有趣吧!他以容量作为单位喔!;
3、 End:此分区的结束位置在这颗磁盘的多少MB处?;
4、 Size:由上述两者的分析,得到这个分区有多少容量;
5、 Filesystem:分析可能的文件系统类型为何的意思!;
6、 Name:就如同gdisk的SystemID之意;

不过start 与 end 的单位竟然不一致!好烦~如果你想要固定单位,例如都用 MB 显示的话,可以这样做:

parted /dev/sda unit mb print

如果你想要将原本的 MBR 改成 GPT 分区表,或原本的 GPT 分区表改成 MBR 分区表,也能使用 parted ! 但是请不要使用 sda 来测试!因为分区表格式不能转换!因此进行下面的测试后,在该磁盘的系统应该是会损毁的! 所以我拿一颗没有使用的U盘来测试,所以文件名会变成 /dev/vda 喔!再讲一次!不要恶搞喔!

下面操作危险,无法复原!

[root@study ~]# parted /dev/vda print
Model: ATA QEMU HARDDISK (scsi)
Disk /dev/vda: 2148MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos 确实显示的是 MBR 的 msdos 格式喔!
[root@study ~]# parted /dev/vda mklabel gpt
Warning: The existing disk label on /dev/sda will be destroyed and all data on
this disk will be lost. Do you want to continue?
Yes/No? y
[root@study ~]# parted /dev/vda print
# 你应该就会看到变成 gpt 的模样!只是...后续的分区就全部都死掉了!

接下来我们尝试来创建一个全新的分区吧!再次的创建一个 512MB 的分区来格式化为 vfat,且挂载于 /data/win 喔!

[root@study ~]# parted /dev/sda print
.....(前面省略).....
Number Start End Size File system Name Flags
7 36.0GB 36.5GB 522MB primary
[root@study ~]# partprobe
[root@study ~]# lsblk /dev/sda7
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda7 252:7 0 498M 0 part 要确定它是真的存在才行!
[root@study ~]# mkfs -t vfat /dev/sda7
[root@study ~]# blkid /dev/sda7
/dev/sda7: SEC_TYPE="msdos" UUID="6032-BF38" TYPE="vfat"
[root@study ~]# nano /etc/fstab
UUID="6032-BF38" /data/win vfat defaults 0 0
[root@study ~]# mkdir /data/win
[root@study ~]# mount -a
[root@study ~]# df /data/win
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda7 509672 0 509672 0% /data/win

事实上,你应该使用 gdisk 来处理 GPT 分区就好了!不过,某些特殊时刻,例如你要自己写一只脚本,让你的分区全部一口气创建, 不需要 gdisk 一条一条指令去进行时,那么 parted就非常有效果了!因为他可以直接进行 partition 而不需要跟用户互动!这就是它的最大好处! 建议至少你要操作过几次 parted ,知道这家伙的用途!未来有需要再回来查!或使用 man parted 去处理喔!