Linux磁盘分区及文件系统管理详解

磁盘,提供持久的数据存储,它不像我们的内存,如果突然断电了,在内存中的数据一般都会被丢掉了,内存中的数据在保存的时候,会被写到硬盘里面,磁盘也是一种I/O设备。

我们都知道磁盘分区完成之后,还要进行格式化,这个格式化操作就是指定文件系统,文件系统的本质就是对一个存储设备上的元数据和数据就行组织,最终把数据有组织的放在可以长期存储的设备中。

本文主要是介绍可Linux中的磁盘分区和文件系统管理。

磁盘的接口类型:

IDE:一种较老的接口技术,价格低廉,兼容性强,传输速度可达133MB/s;

SCSI:主要应用于中、高端服务器中,支持热拔插,价格较高,其中UltraSCSI可达320MB/S,UltraSCSI640可达640MB/S;

Linux磁盘分区及文件系统管理详解

SCSI接口

SATA:主要用于PC上,串口硬盘,可达6gbps;

SAS:是一种串行链接的SCSI接口技术,向下兼容SATA,速度快;

USB:一种便携的存储设备,USB3.0理论最大传输速度可达500MB/s,现在最新的USB3.1Gen 2最高可达10Gbps。

 

并口和串口的区别:

并口:同一线缆可以接多块设备,IDE和SCSI为并口硬盘;

串口:同一线缆只可以接一个设备,SATA、SAS和USB为串口,抗干扰能力强。

我们都知道作为linux的哲学思想之一,一切皆文件,在linux中使用设备文件来标识不同的硬盘,也就是设备的访问接口,在Linux中I/O设备分为2倍,字符设备和块设备,基于不同的功能进行分类的:

(1)字符设备:线性访问的,数据的交换单位是“字符”,提供的连续的数据流,不支持随机存取,举例来说,键盘、调制解调器都是典型的字符设备;

(2)块设备:可以提供随机访问,数据交换的单位是“块”,硬盘、CD-ROM驱动器都是典型的块设备,应用可以寻址磁盘上的任何位置,并读取数据。

 Linux磁盘分区及文件系统管理详解

在Linux系统中,c代表字符设备,b为块设备(红色部分标识)。

后面黄色标注的两行为设备号:

主设备号:左列,区分设备类型,用于标明设备所需要的驱动程序;

次设备号:右列,区分同种类型下的不同的设备。

 

 mknod命令

 mknod可以创建设备文件,格式如下:

mknod  [OPTION]...  NAME  TYPE  [MAJOR  MINOR]
选项:
-m MODE:创建后的设备文件的访问权限
mknod /dev/ttyUSB32 c 188 32

 linux的设备文件都是放在/dev目录下的,应用程序可以通过这些设备文件完成都设备的读写等操作。之前写过设备都有主次设备号,linux有约定俗成的编号,如硬盘的主设备号在CentOS6和7中为8:

 根据接口类型的不同,设备的文件名命令也有一些规定,在centos如下:

 Linux磁盘分区及文件系统管理详解

在引用设备的时候可以通过以下三种方式:

1.设备文件名,也就是/dev目录下的文件名;

2.系统卷标(volume label);

3.UUID,唯一表示码,能够唯一的表示一个设备。

 

MBR和GPT

一块磁盘是可以被分割成多个分区,从Windows的角度来看,就是C,D,E分区。磁盘分区的方式有MBR和GPT。

 

 MBR(Master Boot Record)

总共大小为512字节,存在于磁盘的第0个扇区。

446bytes:引导启动操作系统的程序;

64bytes:分区表,每16bytes标识一个分区,一共能够有4个主分区,但是如果想划分更多的区,可以指定扩展分区,比如分为3个主分区,一个扩展分区,而扩展分区可以划分为若干个逻辑分区。

 Linux磁盘分区及文件系统管理详解

 综上所述,如果使用MBR分区,就必须至少有一个扩展分区,然后将扩展分区分成逻辑分区,逻辑分区的序号从5开始。

 

 GPT(GUID Partition Table):

MBR是另一种分区方式:

1):GPT分区表中最多可以支持128个主分区

2):突破了MBR单个分区只能是2.2T的限制,最大支持1EB容量

在GPT中主分区、扩展分区和模糊分区的概念就淡化了很多。

分区工具

 fidisk

 1.查看磁盘分区

fdisk -l device...:查看指定磁盘设备的分区情况

 Linux磁盘分区及文件系统管理详解

 2.管理分区

 fdisk为MBR方式的分区工具,提供了交互式的接口来管理分区所有的操作,都是在内存中完成的,当使用w保存的时候,才真正去创建或修改分区。

fdisk device

 我们来试试,可以看到使用fdisk加设备名,就进入到了一个交互式的界面,输入m即可获得帮助:

[root@localhost ~]# fdisk /dev/sdb
欢迎使用 fdisk (util-linux 2.23.2)。
更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。
Device does not contain a recognized partition table
使用磁盘标识符 0x3918c6ef 创建新的 DOS 磁盘标签。
命令(输入 m 获取帮助):m
命令操作
   a   toggle a bootable flag
   b   edit bsd disklabel
   c   toggle the dos compatibility flag
   d   delete a partition                <=======删除已有分区
   g   create a new empty GPT partition table
   G   create an IRIX (SGI) partition table
   l   list known partition types        <======列出已知的分区类型
   m   print this menu                   <=======查看帮助信息
   n   add a new partition               <=======创建新的分区
   o   create a new empty DOS partition table
   p   print the partition table         <======显示现有分区信息
   q   quit without saving changes       <======不保存退出
   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)

 举个例子:现在新加了一块120G的磁盘,分为3个主分区,每个区20G,余下的空间都给扩展分区并添加一个20G的逻辑分区。

[root@localhost ~]# fdisk /dev/sdb
欢迎使用 fdisk (util-linux 2.23.2)。
更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。
Device does not contain a recognized partition table
使用磁盘标识符 0x3918c6ef 创建新的 DOS 磁盘标签。
命令(输入 m 获取帮助):n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
分区号 (1-4,默认 1):1
起始 扇区 (2048-251658239,默认为 2048):
将使用默认值 2048
Last 扇区, +扇区 or +size{K,M,G} (2048-251658239,默认为 251658239):+20G
分区 1 已设置为 Linux 类型,大小设为 20 GiB
命令(输入 m 获取帮助):n
Partition type:
   p   primary (1 primary, 0 extended, 3 free)
   e   extended
Select (default p): p
分区号 (2-4,默认 2):2
起始 扇区 (41945088-251658239,默认为 41945088):
将使用默认值 41945088
Last 扇区, +扇区 or +size{K,M,G} (41945088-251658239,默认为 251658239):+20G
分区 2 已设置为 Linux 类型,大小设为 20 GiB
命令(输入 m 获取帮助):n
Partition type:
   p   primary (2 primary, 0 extended, 2 free)
   e   extended
Select (default p): p
分区号 (3,4,默认 3):
起始 扇区 (83888128-251658239,默认为 83888128):
将使用默认值 83888128
Last 扇区, +扇区 or +size{K,M,G} (83888128-251658239,默认为 251658239):+20G
分区 3 已设置为 Linux 类型,大小设为 20 GiB
命令(输入 m 获取帮助):n
Partition type:
   p   primary (3 primary, 0 extended, 1 free)
   e   extended
Select (default e): e
已选择分区 4
起始 扇区 (125831168-251658239,默认为 125831168):
将使用默认值 125831168
Last 扇区, +扇区 or +size{K,M,G} (125831168-251658239,默认为 251658239):
将使用默认值 251658239
分区 4 已设置为 Extended 类型,大小设为 60 GiB
命令(输入 m 获取帮助):n
All primary partitions are in use
添加逻辑分区 5
起始 扇区 (125833216-251658239,默认为 125833216):
将使用默认值 125833216
Last 扇区, +扇区 or +size{K,M,G} (125833216-251658239,默认为 251658239):+20G
分区 5 已设置为 Linux 类型,大小设为 20 GiB

 查看分区情况:

[root@localhost ~]# fdisk -l /dev/sdb 
磁盘 /dev/sdb:128.8 GB, 128849018880 字节,251658240 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x3918c6ef
   设备 Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048    41945087    20971520   83  Linux
/dev/sdb2        41945088    83888127    20971520   83  Linux
/dev/sdb3        83888128   125831167    20971520   83  Linux
/dev/sdb4       125831168   251658239    62913536    5  Extended
/dev/sdb5       125833216   167776255    20971520   83  Linux 

 parted

 这个工具既可以做MBR的分区,又可以做GPT的分区,主要时候用来做GPT的。

 1.查看分区情况:

parted -l device   (亲测:竟然也可以使用fdisk -l指定设备查看)

 2.管理分区

 parted也提供了交互式的接口来管理分区,输入help查看帮助,我们来看一下:

[root@localhost ~]# parted
GNU Parted 3.1
使用 /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) help                                                             
  align-check TYPE N                        check partition N for TYPE(min|opt) alignment
  help [COMMAND]                           print general help, or help on COMMAND
  mklabel,mktable LABEL-TYPE               create a new disklabel (partition table)
  mkpart PART-TYPE [FS-TYPE] START END     make a partition
  name NUMBER NAME                         name partition NUMBER as NAME
  print [devices|free|list,all|NUMBER]     display the partition table, available devices, free space, all found
        partitions, or a particular partition
  quit                                     exit program
  rescue START END                         rescue a lost partition near START and END
  rm NUMBER                                delete partition NUMBER
  select DEVICE                            choose the device to edit
  disk_set FLAG STATE                      change the FLAG on selected device
  disk_toggle [FLAG]                       toggle the state of FLAG on selected device
  set NUMBER FLAG STATE                    change the FLAG on partition NUMBER
  toggle [NUMBER [FLAG]]                   toggle the state of FLAG on partition NUMBER
  unit UNIT                                set the default unit to UNIT
  version                                  display the version number and copyright information of GNU Parted
(parted)                                  
 


(看起来比fdisk麻烦多了)

我们来举个例子来说明parted的使用方法:
1)首先选择要分区的设备,使用select Device

(parted) select /dev/sdc
使用 /dev/sdc

 2)选择分区格式为GPT

mklabel gpt

 下面是命令的使用帮助

(parted) help mklabel 
  mklabel,mktable LABEL-TYPE               create a new disklabel (partition table)
    “标签类型”是以下任意一项:aix, amiga, bsd, dvh, gpt, mac, msdos, pc98, sun, loop

 3)使用mkpart分区时,不需要指定分区的数字标识(在MBR中可能要指定1-4或更多),可以直接给它加上名称,这说明在GPT分区的情况下,主分区扩展分区已经变得不那么重要了,分区的起始点最好从1开始

(parted) mkpart 
分区名称?  []? my_data1                                                  
文件系统类型?  [ext2]?     #文件系统先不用管,后面会讲到                                               
起始点? 1        #                                                        
结束点? 2048     #默认为M

 4)这样一个分区就创建好了,可以使用print查看

(parted) print                                                            
Model: ATA VMware Virtual I (scsi)
Disk /dev/sdc: 53.7GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 
Number  Start   End     Size    File system  Name      标志
 1      1049kB  2048MB  2047MB               my_data1

 5)让我们再来新建一个分区,新建分区的起始点就是上一个分区的结束点

(parted) mkpart                                                           
分区名称?  []? my_data2
文件系统类型?  [ext2]?                                                   
起始点? 2048
结束点? 4096                                                             
(parted)                                                                  
(parted) print                                                            
Model: ATA VMware Virtual I (scsi)
Disk /dev/sdc: 53.7GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 
Number  Start   End     Size    File system  Name      标志
 1      1049kB  2048MB  2047MB               my_data1
 2      2048MB  4096MB  2048MB               my_data2

 6)作为linux的哲学思想之一,避免与用户交互,我们也可以使用以下方式来创建新的分区

(parted) mkpart my_data3 4096 6144                                        
(parted)                                                                  
(parted) print                                                            
Model: ATA VMware Virtual I (scsi)
Disk /dev/sdc: 53.7GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 
Number  Start   End     Size    File system  Name      标志
 1      1049kB  2048MB  2047MB               my_data1
 2      2048MB  4096MB  2048MB               my_data2
 3      4096MB  6144MB  2048MB               my_data3

 7)parted使用quit退出即生效

(parted) quit                                                             
信息: You may need to update /etc/fstab.
[root@localhost ~]#
以上就是2种比较常用的分区工具了
特别要注意的是,在已经分区并且已经挂载在根文件系统的目录上的设备,再在这个设备上创建新的分区(比如在扩展分区上创建逻辑分区),内核可能在创建完成后无法直接识别。
可以查看/proc/partitions,确认内核是否已经识别:
 
[root@localhost ~]# cat /proc/partitions 
major minor  #blocks  name
   8       16  125829120 sdb
   8       17   20971520 sdb1
   8       18   20971520 sdb2
   8       19   20971520 sdb3
   8       20          1 sdb4
   8       21   20971520 sdb5
   8       32   52428800 sdc
   8       33    1998848 sdc1
   8       34    1999872 sdc2
   8       35    1999872 sdc3
   8        0   20971520 sda
   8        1     512000 sda1
   8        2   20458496 sda2
  11        0    4277248 sr0
 253        0   16261120 dm-0
 253        1    2097152 dm-1
 253        2    2097152 dm-2

 如果没有识别可以使用以下两种方式通知内核强制重读磁盘分区表:

partx -a device
kpartx -af device

 如果命令一次不能成功,请多试几次。

 

文件系统的特性

磁盘分区完成之后,还要进行格式化,这个格式化操作就是指定文件系统,文件系统的本质就是对一个存储设备上的元数据和数据就行组织,最终把数据有组织的放在可以长期存储的设备中。

传统的说法是一个分区只能格式化成一种文件系统,但是由于新技术的产生,LVM或者RAID,一个分区可以被格式化成多个文件系统,也可以将多个分区格式格式化成一个文件系统。

数据一般分为实际的数据(实际的数据,一首mp3)和元数据(文件的属性和权限等),它们在文件系统中存放的位置是不同的。实际的数据是存储在data block中,元数据则是存储在innode中,除此之外还有一个superblock。

superblock:记录了文件系统的整体信息,包括innode/block的总量、使用量和剩余量和文件系统的格式等

inode:记录文件的属性,一个文件占一个inode,同时也记录了文件所在的block号

block:实际记录文件的内容,若文件大小大于block,则占用多个block块

 

 下面就来讲一下inode和block之间的关系:

 1.索引式文件系统

 若一个文件的inode号是4,此中存放了其block的位置:2,7,13,15,那么操作系统读取数据的时候,就可以根据inode中block的位置一次性将数据读取出来。

 Linux磁盘分区及文件系统管理详解

2.链式文件系统

 和索引式文件系统不同的是莲式读取文件方式,常见于U盘的FAT格式,这种文件系统没有inode的存在,每个block的号码都记录在前一个block中。

 Linux磁盘分区及文件系统管理详解

 3.磁盘重组

 磁盘重组的目的就是将写在磁盘中离散的block重新组织一下,将同一个文件的block块集合在一起,以便于数据的读取。导致数据离散的原因,一般是由于文件系统使用的时间过长,非常多次的数据的操作,比如删除、增加和修改的次数很多。

 文件系统的类别

Linux的文件系统: ext2(无日志功能), ext3, ext4, xfs, reiserfs, btrfs
光盘:iso9660
网络文件系统:nfs, cifs
集群文件系统:gfs2, ocfs2
内核级分布式文件系统:ceph
windows的文件系统:vfat, ntfs
伪文件系统:proc, sysfs, tmpfs, hugepagefs
Unix的文件系统:UFS, FFS, JFS
交换文件系统:swap
用户空间的分布式文件系统:mogilefs, moosefs, glusterfs

 

 linux下的EXT2文件系统

EXT2是一种比较旧的文件系统了,从Centos7开始文件系统已经开始使用了XFS,但是这种使用inode为基础的文件系统还是要了解的,毕竟后面也出现了它的升级版本,EXT3和EXT4。

前面说过inode记录是文件的权限和属性,inode和block在文件系统创建好之后就已经分好了的,但是我们想一想,如果一个硬盘有500G甚至更大,inode和block都放在一起就会显得不是很合理,数量过大,不容易去管理。所有在EXT2文件系统中在格式化的时候将文件系统分为多个区块,称为block group,每个block group都有自己的block/inode/superblock。

下面我们就来看看一个block group的大致样子:

 Linux磁盘分区及文件系统管理详解

在文件系统的最前面有一个Boot Sector,可以安装开机管理程序,这样我们就能将不同的开机管理程序安装在个别的文件系统之前,而不用覆盖整个磁盘的MBR,这样就能做出多重开机的环境。

 

 block group的内容:

date block:用来放置文件内容的地方,大小一般为1k、2k、4k,block的大小在格式化之后就不能再改变了,每个block就能存放一个文件的数据。

inode table:记录了文件的权限,文件的大小,时间戳,flag或者该文件的真正指向

superblock:block和inode的数量信息,文件系统的时间戳,一个有效比特,该值为0代表已经被挂载,该值为1则没有被挂载

Filesystem Description:文件系统描述说明,描述了每个block group的开始和结束的block号码,已经说明了superblock\bitmap\inodemap\data block分别在哪个一个block号码之间。

block bitmap:block位图,记录block的使用情况,标明了哪些block是空的,我们在删除的文件的时候,会发现很快,删除文件操作其实就是改变了该文件占用的bitmap的位置为空,block的文件暂时没有删除,这就是我们的数据可以被找回的原因

inode bitmap:inode位图,与block bitmap的功能类似,记录的是使用与未使用的inode号码。

 

目录的Inode

文件系统会给目录分配至少一个block,inode记录了权限和属性以及分配到的block号,而block则记录了这个目录下的文件名与该文件名所占用的inode号码。

下面描述读取一个目录下文件的流程:

举例:root读取/tmp/test.txt文件的过程:

1./的inode:通过挂载点信息找到inode号码为128的根目录的inode,取得权限和block号

2./的block:根据block的号码,查看block的内容,找到目录tmp/的文件名和其inode号

3.tmp/的inode:根据inode,获取权限信息和block号

4.tmp/的block:查看对应的block的内容,找到test.txt的inode号

5.test.txt的inode号:根据inode,获取权限信息和对应的block号

6.test.txt的block:获取文件的实际内容

 

日志式文件系统功能

数据存放区域:inode table,data block

metadata:中介数据,变化次数频繁,superblock,block bitmap和inode bitmap

新增一个文件的过程:

1.根据目录文件的inode确定用户是否有权限

2.根据inode位图找到没有使用的inode号,在inode table写入权限等信息

3.根据block位图找到没有使用的block号,在block中写入实际数据,更新到inode中去

4.更新inode位图和block位图,并更新到superblock中

一般一个完整的新建文件的过程就如上

但是但是出现特殊情况,比如断电,可能会出现数据仅仅写到了inode table和block中却没有更新inode位图和block位图,也没有更新superblock,那就导致中介数据和真正存储数据的内容不一致。

在EXT2中,要使用e2fsck这个工具,要遍历整个文件系统,!!不敢想象啊!

所以就出现了日志式文件系统:

在文件系统中又单独划分一个区块,记录了写入或修改文件时的信息

1.当要写入一个文件的时候,就在日志区块记录一下某个文件要写入了

2.写入文件的数据,更新metadata数据

3.完成数据和metadate的更新,在日志记录区块当中完成对该文件的记录

这样,当发生意外的时候,我们可以直接检查日志记录区块,查看哪些文件有问题,然后做出校验即可

EXT2不支持日志式文件系统,EXT3和EXT4都支持日志式文件系统,并向下兼容EXT2

 

VFS

VFS(Virtual Filesystem Switch),linux系统通过VFS的核心功能去读取文件系统。

比如/是使用的是/dev/sda1,其文件系统是ext2格式的,而/home使用的/dev/sda2,其格式为xfs,如果我们现在要读取/home/Frank,直接cat就行了,我们有指定要用什么文件系统的模块去读取吗?没有,这个就是VFS的功能,VFS可以管理所有的filesystem,示意图如下:

 Linux磁盘分区及文件系统管理详解

相关推荐