5. Linux文件系统

时间:2023-02-09 13:00:15

1. 简介

  1. 磁盘类型:
  • 机械硬盘:盘片、磁头、转轴、控制电机
  • 固态硬盘:SSD
  1. 硬盘尺寸(宽度)
  • 2.5英寸
  • 3.5英寸
  1. 接口
  • 插头
  • IDE/SATA
  • 串口/并口
  • 慢/快
  • 老/新
  1. 转速(只有机械硬盘)
  • 每分钟旋转的速度(rpm)
  • 5400r/m
  • 7200r/m
  • 15000r/m
  1. 厂商
  • 西部数据
  • 希捷
  1. 术语(磁盘非固态)
  • 柱面
  • 盘片
  • 磁道:同心圆
  • 扇面
  • 扇区,每个扇区512字节
  1. 命名:计算机自动命名
  • SATA口:​​/dev/sda​​ ​​/dev/sdb​​,是一个文件
  • ​/dev​​:设备文件目录,
  • ​s​​:SATA口 | SCSI口 | USB口,​​h​​:IDE口 | ATA口
  • ​d​​:disk
  • ​a​​ ​​b​​:第一、二块
  • 分区继续编号​​1, 2, 3...​​ ​​/dev/sda1​​ ​​/dev/sda2​
  1. 分区方式
  • MBR:主引导启动记录(Master Boot Record)位于磁盘最前边的一段引导,占据512字节
  • 前446字节放Boot Loader,引导操作系统的启动;
  • 64字节每16字节标识一个分区,最多支持4个分区;
  • 最后2字节是Magic Number,一定是​​55AA​​是分区结束标志;
  • 支持的最大的容量<2TB;
  • 超过4个分区,需要放弃主分区,改为3个逻辑分区和1个扩展分区。
  • GPT:统一分区表(GUID Partition Table)
  • 支持超过2TB的容量
  • 支持128个分区

2. 管理磁盘

2.1 查看磁盘信息

买来磁盘插入,管理之前先查看磁盘的信息。而系统会自动给新插入的磁盘命名,这个不用手动命名。

一个磁盘分区由四个字符组成,前三个字符​​sd<a>​​代表是哪块磁盘,最后一个数字代表是哪一块分区。最前面权限前面的​​b​​代表是块block设备。

$ ll /dev/sd*        # 查看磁盘信息
brw-rw---- 1 root disk 8, 0 16 11:29 /dev/sda
brw-rw---- 1 root disk 8, 1 16 11:29 /dev/sda1
brw-rw---- 1 root disk 8, 2 16 11:29 /dev/sda2
brw-rw---- 1 root disk 8, 5 16 11:29 /dev/sda5

$ lsblk # 列出块设备
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 1024M 0 rom
sda 8:0 0 40G 0 disk
├─sda2 8:2 0 1K 0 part
├─sda5 8:5 0 958M 0 part [SWAP]
└─sda1 8:1 0 39.1G 0 part /
sr1 11:1 1 1024M 0 rom

$ fdisk -l [/dev/sda]

2.2 分区

​fdisk​​指MBR格式分区。​​gdisk​​指GPT格式分区。

# fdisk常用子命令
m:help
p:print,查看当前分区信息
n:new
d:delete
w:save & quit
q:quit
l:查看分区类型信息
t:type,调整分区类型
L:查看分区的编号

:warning: 请记住,下面操作适合新加硬盘分区,如果是有东西的磁盘,会损坏原有文件。请谨慎操作!!!

  1. 创建分区
$ fdisk /dev/sdb
欢迎使用 fdisk (util-linux 2.23.2)。

更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。

Device does not contain a recognized partition table
使用磁盘标识符 0xe99ad669 创建新的 DOS 磁盘标签。

命令(输入 m 获取帮助): n # add a new partition
Partition type:
p primary(0 primary, 0 extended, 4 free)
e extended
Select (default p): p
分区号 (1-4, 默认 1): 1
起始 扇区 (2048-10485759), 默认为 2048) : # 主分区的范围,单位是512Bytes,即一个扇区是512字节。扇区编号从0开始。这里默认即可,即直接回车,0-2047放的是MBR,记录每个分区信息。
last 扇区, +扇区 or +size{K,M,G} (2048-10485759, 默认为 10485749) : +2G # 这里直接使用这种+nG就可以了。
分区 1 已设置为 Linux 类型, 大小设为 2 GiB

命令(输入 m 获取帮助): w # 真的要去做分区了,w之后就会真的创建分区
The partition table has been altered!

Calling ioctl() to re- read partition table.
正在同步磁盘。
  1. 刷新下分区信息,让内核知道有了新的分区并读取。内核已知的分区位于/proc/partitions文件中,可以查看。有时候partprobe也不好使,就需要重新启动计算机了。RHEL 6.x还支持partx命令刷新,重读分区表。
# 不写参数则是读取整个分区表
$ partprobe [/dev/sdb] # 分区准备,partition probe,就是刷新下证明分区做好了
  1. 查看分区。会发现已经对/dev/sdb做好了一个分区:/dev/sdb1
$ fdisk -l /dev/sdb
磁盘 /dev/sdb: 5366 MB, 5368709210 字节, 10485760 个扇区
Units = 扇区 or 1 * 512 = 512 bytes
扇区大小(逻辑/物理): 512 字节 / 512 字节
I/O大小(最小/最佳): 512 字节 / 512 字节
磁盘标签类型: dos
磁盘标识符: 0xe99ad669

设备 Boot Start End Blocks Id System
/dev/sdb1 2048 4196351 2097152 83 Linux
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 20G 0 disk
|-sda1 8:1 0 1G 0 part /boot
|-sda2 8:2 0 19G 0 part
|-centos-root 253:0 0 17G 0 lvm /
|-centos-swap 253:1 0 2G 0 lvm [SWAP]
sdb 8:16 0 5G 0 disk
|-sdb1 8:17 0 2G 0 part

2.2 格式化

创建好的分区需要格式化之后才能使用,也就是创建文件系统,这里是高级格式化,低级格式化是在出厂的时候就已经做好了。

查看当前内核所支持的文件系统:​​cat /proc/filesystems​​。

创建文件系统的命令有:​​mke2fs​​​,​​mkfs​​​,​​mkfs.ext4​​​。其中​​mkfs.ext4 == mkfs -t ext4​​。后续有关文件系统的命令查看下述文件系统小节

# $ mke2fs [option] [/dev/sdb1]               # 专门管理EXT类型的文件系统。
# -j创建EXT3+类型的文件系统
# -b指定块大小,默认为4096,可用取值1024、2048或4096
# -L指定卷标,即分区名称
# -m指定为超级用户保留的区块大小的百分比,不需要写%,默认是5%
# -i指定多少个字节一个inode,默认是8192bytes/inode
# -N指定总共可创建的inode个数
# -F指定强制创建文件系统
# -E用户指定额外文件系统属性

# make file system extend4
# 创建 文件系统 扩展系统:是文件系统的类型
# /dev/sdb1 第2块串口硬盘的第一个分区准备格式化了
# $ mkfs.ext4 /dev/sdb1
$ mkfs -t ext4 /dev/sdb1 # 和上一条命令一样,只是-t指定类型
mke2fs 1.42.9 (28-Dec-2013)
文件系统标签=
OS type: Linux
块大小=4096(log=2)
分块大小=4096(log=2)
Stride=0 blocks, Stripe width=0 blocks
131072 inodes, 524288 blocks
25214 blocks (5.00%) reserved for the super user
第一个数据块=0
Maximum filesystem blocks=536870912
16 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912

Allocating group tables: 完成
正在写入inode表: 完成
Creating journal (16384 blocks): 完成 # 日志功能
Writing superblocks and filesystem accounting information: 完成

This filesystem will be automatically checked every 20 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.

2.3 挂载与卸载

挂载就是给创建好的文件系统寻找一个入口。

$ mkdir /mnt/disk1

# 设备可以用:设备文件、LABEL="LABLE_NAME"、UUID="UUID"
# 挂载点要求目录需要事先存在,此目录没有被其它进程使用,目录原有文件将会被暂时屏蔽。
# 没有参数:显示当前系统已经挂载的设备以及挂载点
# -a:表示挂载/etc/fstab文件中定义的所有文件系统
# -n:默认情况下,mount命令每挂载一个设备,都会把挂载的设备信息保存到/etc/mtab文件,-n表示静默不把信息写入此文件
# -t:指定要挂载的文件系统类型,可以不指定,mount会自动调用blkid命令获取文件系统类型
# -r:只读挂载,挂载光盘常用此选项
# -w:读写挂载,默认挂载方式
# -o:指定额外的挂载选项,即指定文件系统启用的属性
# async:异步写入,默认
# atime:每次更新inode时间戳。调优时最好关闭,noatime
# auto,可以使用-a选项挂载
# defaults:rw, suid, dev, exec, auto, nouser, and async
# dev:当前文件系统有其它设备文件系统就启用
# exec:允许二进制文件有执行权限的执行,对于U盘最后不要指定
# _netdev:网络设备映射到本地,网络不可用将可以自动跳过。挂载网络设备时有用
# owner:使得普通非root用户但设备拥有者可以挂载文件系统。同时使用nosuid和nodev
# remount:重新挂载,此时不指定挂载点就挂载在原挂载点
# ro:只读挂载
# rw:读写挂载
# sync:同步方式挂载
# suid:不安全,尽量nosuid
# loop:挂载本地回环设备,例如*.iso文件。
# --bind:
# --move:
$ mount [options] [-o options] [DEVICE] [MOUNT_POINT]

$ mount [-t ext4] /dev/sdb1 /mnt/disk1
$ df -hT # -h人类友好,-T显示类型
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda1 ext4 39G 32G 4.9G 87% /
/dev/sdb1 ext4 2.0G 6.0M 1.8G 1% /mnt/disk1

# 卸载要求没有被任何进程使用,否则显示device is busy
$ umount /mnt/disk1 # 卸载,挂载的反向操作

挂载前​​/mnt/disk1​​​使用的是原来的磁盘,但是挂载之后,将会使用新的磁盘空间,即​​/dev/sdb1​​​。但是这种挂载的方式,只会本次生效,下次开机就不会在了。如果要永久挂载需要写入到​​/etc/fstab​​文件中。

挂载点会屏蔽掉原有目录下的文件和目录,测试如下:

# 1. 先在 /mnt/sda3 目录下创建5个文件
root@basil:/mnt/sda3# ls
file1 file2 file3 file4 file5

# 2. 挂载/dev/sda4到/mnt/sda3
root@basil:/mnt/sda3# mount /dev/sda4 /mnt/sda3

# 3. 再次查看/mnt/sda3目录下的文件
root@basil:/mnt/sda3# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 465.8G 0 disk
├─sda1 8:1 0 200M 0 part /boot/efi
├─sda2 8:2 0 59.2G 0 part
├─sda3 8:3 0 598M 0 part
├─sda4 8:4 0 143.4G 0 part /mnt/sda3
└─sda5 8:5 0 262.4G 0 part /
sr0 11:0 1 1024M 0 rom
root@basil:/mnt/sda3# ls /mnt/sda3
'$RECYCLE.BIN' DevSft Document Download DTLFolder ProgramFiles 'System Volume Information'

# 4. 卸载/dev/sda4
root@basil:/mnt/sda3# umount /mnt/sda3

# 5. 再次查看/mtn/sda3
root@basil:/mnt/sda3# ls /mnt/sda3
file1 file2 file3 file4 file5

卸载的时候有时候一直提示​​device is busy​​​,可以通过​​fuser -v​​查看正在使用该文件系统的文件和套接字文件。

$ fuser -v /mnt/swapfile
USER PID ACCESS COMMAND
/mnt/swapfile: root kernel swap /mnt/swapfile

# 杀死进程:终止正在访问此挂载点的所有进程
$ fuser -km /mnt/swapfile

# 再次卸载
$ umount /mnt/swapfile

2.4 相关​​/etc/​​下文件

  1. ​/etc/fstab​​是文件系统的配置文件。OS在开机初始化时,会自动挂载此文件中定义的每个文件系统。其格式是:​​设备 挂载点 文件系统类型 挂载选项 转储频率(没多少天做一次完全备份,0不备份,1每天,2每2天,...) 文件系统检测次序(只有根为1,0表示不检查)​​。设备可以用设备目录、UUID、卷标来指定。​​mount -a​​可以挂载定义在该文件的所有文件系统。
$ cat /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a device; this may
# be used with UUID= as a more robust way to name devices that works even if
# disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
UUID=C14D-581B /boot/efi vfat umask=0077 0 2
UUID=5938cf13-d43f-4f50-bdbe-3b8349413419 / ext4 defaults 0 1
/mnt/swapfile swap swap defaults 0 0

其中修改挂载​​options​​​对应的可以在​​defaults​​​后面加上","继续添加,如​​defaults,acl​​。

  1. ​/etc/mtab​​​:文件系统挂载后的相关信息会写入​​/etc/mtab​​​,挂载时使用​​mount -n​​将不会写入该文件。

3. 逻辑卷LVM

3.1 MBR

​MBR(Master Boot Record)​​主引导启动记录,位于0磁道的0扇区的512字节,不属于操作系统,属于磁盘自己。

  • 前446字节放Boot Loader,引导操作系统的启动;
  • 64字节每16字节标识一个分区,最多支持4个分区,所以最大支持2TB的磁盘;
  • 最后2字节是Magic Number,一定是​​55AA​​是分区结束标志。

对于上面一个5G磁盘,继续划分后续3GB的空间,需要重新进行上面的步骤,但是实际进行操作的时候,需要一次性划分完毕。

要是需要超过4个分区,需要放弃一个主分区,采用扩展分区,即​​n​​​之后选择​​e​​,extend分区。主分区和扩展分区在存储数据的时候没有区别,但是主分区才能装系统,而扩展分区不能安装系统。

MBR位于磁盘的0柱面0磁头l扇区处,其中前446字节存储Boot Loader信息,中间64bytes用来存储分区信息,以及其起始扇区号,后2字节存储MBR是。这里只能存储这么多分区。而为了扩展,用户需要放弃一块主分区(一般是最后一块主分区),设置为扩展分区,扩展分区不能存放数据。该扩展分区,再次划分,即为逻辑分区,逻辑分区才能存放数据。

最佳实践:一块硬盘使用MBR方式划分分区,数量上选择:

  • 4个主分区
  • 3个主分区+1个扩展分区(N个逻辑分区)

3.2 逻辑分区

扩展分区一定占用4号分区。

如果已经画好了4个分区,需要在​​fdist /dev/sdb​​中删除一个分区(第4个分区,如有数据做好备份)。

$ fdisk /dev/sdb
命令(输入 m 获取帮助): p

磁盘 /dev/sdb: 5368 MB, 5368709120 字节, 10485760 个扇区
Units = 扇区 or 1 * 512 = 512 bytes
扇区大小(逻辑/物理): 512 字节 / 512 字节
I/O大小(最小/最佳): 512 字节 / 512 字节
磁盘标签类型: dos
磁盘标识符: 0xe99ad669

Device Boot Start End Blocks Id System
/dev/sdb1 2048 4196351 2097152 83 Linux
/dev/sdb2 4196352 4605951 204800 83 Linux
/dev/sdb3 4605952 5015551 204800 83 Linux

命令(输入 m 获取帮助): d
分区号(1-4, 默认 4): 4
分区 4 已删除

命令(输入 m 获取帮助): n
Partition type:
p primary(0 primary, 0 extended, 4 free)
e extended
Select (default p): e
已选择分区 4
起始 扇区 (5015552-10485759), 默认为 5015552) :
将使用默认值 5015552
last 扇区, +扇区 or +size{K,M,G} (5015552-10485759, 默认为 10485749) : # 因为没有分区号了,所以这里一定需要回车,不然后续也没法使用了
分区 4 已设置为 Extended 类型, 大小设为 2.6 GiB

命令(输入 m 获取帮助): n # 但是扩展分区不能直接挂载,需要继续划分逻辑分区
All primary partitions are in use
添加逻辑分区 5
起始 扇区 (5017600-10485759), 默认为 5017600) :
将使用默认值 5017600
last 扇区, +扇区 or +size{K,M,G} (5017600-10485759, 默认为 10485749) : +200M
分区 5 已设置为 Linux 类型,大小设为 200 MiB

命令(输入 m 获取帮助): n # 但是扩展分区不能直接挂载,需要继续划分逻辑分区
All primary partitions are in use
添加逻辑分区 6
起始 扇区 (5429248-10485759), 默认为 5429248) :
将使用默认值 5429248
last 扇区, +扇区 or +size{K,M,G} (5429248-10485759, 默认为 10485749) :
分区 6 已设置为 Linux 类型,大小设为 2.4 GiB

命令(输入 m 获取帮助): p

磁盘 /dev/sdb: 5368 MB, 5368709120 字节, 10485760 个扇区
Units = 扇区 or 1 * 512 = 512 bytes
扇区大小(逻辑/物理): 512 字节 / 512 字节
I/O大小(最小/最佳): 512 字节 / 512 字节
磁盘标签类型: dos
磁盘标识符: 0xe99ad669

Device Boot Start End Blocks Id System
/dev/sdb1 2048 4196351 2097152 83 Linux
/dev/sdb2 4196352 4605951 204800 83 Linux
/dev/sdb3 4605952 5015551 204800 83 Linux
/dev/sdb4 5015552 10485759 2735104 5 Extended
/dev/sdb5 5840896 6252543 204800 83 Linux
/dev/sdb6 6252544 10485759 2530304 83 Linux
命令(输入 m 获取帮助): w # 已经不能继续划分了
$ partprobe /dev/sdb
$ lsblk
$ mkfs -t ext4 /dev/sdb3 # 不能挂载/dev/sdb4因为它就只有500B是逻辑分区信息,逻辑分区同样挂载,但是就不能挂在/dev/sdb4
$ mount -t ext4 /dev/sdb3 /mnt/disk3
$ df -hT

3.3 逻辑卷管理

传统方式下不同的磁盘之间不能混用。即一个超级大的文件(如单个蓝光电影)要跨磁盘存储不可行,即磁盘A和磁盘B剩余空间大于这个文件,但是单个磁盘的空间不足够。物理磁盘的空间是固定的,不便于管理(拷贝、删除、授权)。

逻辑卷(LVM,logic volume manager)是管理磁盘的一种方式,它的特点是随意扩展磁盘的大小,不限制。基本磁盘的过程是购买物理磁盘之后,进行分区、格式化、挂载,LVM的过程是买来物理磁盘之后,变成物理卷,加入卷组,在卷组中抽调空间制作逻辑卷,再格式化、挂载。

术语:

  1. 物理卷,physical volume,PV
  2. 卷组,volume group,VG
  3. 逻辑卷,logic volume,LV
# 1. 买磁盘
# 2. 创建物理卷,把磁盘插入然后转为物理卷
# pvcreate 磁盘位置
$ pvcreate /dev/sdf
Physical volume "/dev/sdf" successfully created.
# 3. 创建卷组
# vgcreate 卷组名 物理卷
$ vgcreate vg1 /dev/sdf
Volume group "vg1" successfully created.
# 4. 创建逻辑卷,必须从卷组名称去拿空间
# lvcreate -L 大小 -n 逻辑卷名 卷组
$ lvcreate -L 200M -n lv1 vg1
Logical volume "lv1" created.
# 5. 格式化
# 先卷组名后逻辑卷名
$ mkfs.ext4 /dev/vg1/lv1
# 6. 挂载
$ mount /dev/vg1/lv1 /mnt/lv1
# 7. 验证
$ df -hT

接下来进行扩容。

# 1. 创建物理卷
$ pvcreate /dev/sdg
# 查看物理卷
$ pvs
PV VG Fmt Attr PSize PFree
/dev/sdf vg1 lvm2 a-- <5.00g 1020.00m
/dev/sdg lvm2 --- <5.00g 5.00g # 还没有加入卷组
# 2. 加入卷组(扩展)
# vgextend 卷组名 物理卷
$ vgextend vg1 /dev/sdg
# 查看卷组
$ vgs
VG #PV #LV #SN Attr VSize VFree
vg1 2 1 0 wz--n- 9.99g 5.99g

# 3. lv扩容(逻辑卷扩容)
$ lvextend -L +4G /dev/vg1/lv1

# 4. fs扩容(文件系统扩容)
$ resize2fs /dev/vg1/lv1
resize2fs 1.42.9 (28-Dec-2013)
Filesystem at /dev/vg1/lv1/ is mounted on /mnt/lv1; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 1
The filesystem on /dev/vg1/lv1 is now 2097152 blocks long.

不要轻易卸载磁盘,否则会出现问题,如果一定需要卸载磁盘,则需要反着来。

4. 交换分区管理SWAP

4.1 简介

物理内存分页(page frame)进行管理,虚拟地址使得程序以为自己可以使用完整的内存空间,OS自动完成虚拟地址和物理地址的映射关系。

SWAP就是一个普通的分区,防止OOM(Out Of Memory),可以“提升”内存容量,其实就是虚拟内存,只不过Linux换了叫法。经常需要使用的数据就可以放到交换分区,可以提升数据的读取速度。

Linux有物理内存就不会使用交换分区。

:star:最佳实践

  1. 一般SWAP的空间是物理内存的2倍。
  2. 大于4GB小于16GB内存的系统,最小需要4GB的交换分区;
  3. 大于16GB小于64GB内存的系统,最小需要8GB的交换分区;
  4. 大于64GB小于256GB内存的系统,最小需要16GB的交换分区;

4.2 创建交换分区

4.2.1 使用空闲磁盘

这里使用的是新的磁盘或者一份不再使用的磁盘分区。

$ free -m
total used free shared buff/cache available
Mem: 3782 1523 243 95 2015 1882
Swap: 0 0 0

Linux系统下磁盘设备的类型主要使用(​​fdist /dev/sdc​​​, ​​m​​​显示帮助,​​L​​​显示类型,​​t​​更换类型)

  • 82:Linux Swap
  • 83:Linux
  • 85:Linux Extend
  • 8e:LVM
# 1. 创建SWAP分区
$ fdisk /dev/sdc

命令(输入 m 获取帮助): n
Partition type:
p primary(0 primary, 0 extended, 4 free)
e extended
Select (default p): p
分区号(1-4, 默认 1) :
起始 扇区 (2048-10485759), 默认为 2048) :
将使用默认值 2048
Last 扇区, +扇区 or +size{K,M,G} (2048-10485759, 默认为 10485749) : +2G
分区 1 已设置为 Linux 类型, 大小设为 2 GiB

命令(输入 m 获取帮助): t # 更改分区的类型,这个可以不改,也就是不需要下面的82
已选择分区 1
Hex 代码(输入 L 列出所有代码): 82 # 使用的是82代表的是 Linux 交换分区,这里一定需要修改!!!
已将分区"Linux"的类型更改为"Linux swap / Solaris"

命令(输入 m 获取帮助): w # 保存即可

$ partprobe /dev/sdc
$ ll /dev/sdc*

# 2. 格式化,创建SWAP文件系统
$ mkswap /dev/sdc1 # 格式化,创建文件系统
正在设置交换空间版本 1, 大小 = 2097148 KiB
无标签, UUID=51bd294d-7fb1-49c7-8807-696d74b3b74b

# 3. 挂载
# -a:启用所有定义在/etc/fstab中的交换设备
$ swapon /dev/sdc1 # 挂载swap分区
$ swapoff /dev/sdc1 # 卸载swap分区

# 4. 验证现在的交换分区
$ free -m # -m表示以Mb为单位查看

4.2.2 使用本地回环文件

参考这个​​Linux SWAP分区和虚拟内存​​。临时救急还行,正常使用性能差。

# 1. 创建一个由连续空间的swap文件
# 如备份MBR数据:dd if=/dev/sda of=/mnt/usb/mbr.backup bs=512 count=1
# 如还原MBR数据:dd if=/mnt/usb/mbr.backup of=/dev/sda bs=512 count=1
# dd:用于复写命令,类似cp命令,但是cp以文件为单位,dd是流数据,可以只复制文件的某些字节
# if=/src:复写的是哪里的信息,这里是/dev/zero是一个全0文件,就是0
# of=/dst:写到哪里去,这里是/mnt下的swapfile文件,swapfile为自己创建,这个路径也可以换成别的
# bs=#:block size,就是块大小,这里是1MB
# count=#:复写次数,count * bs ≈ 4GB
# seek=#:从哪里开始,之前的都跳过了。
$ dd if=/dev/zero of=/mnt/swapfile bs=4M count=1000
1000+0 records in
1000+0 records out
4194304000 bytes (4.2 GB, 3.9 GiB) copied, 93.8471 s, 44.7 MB/s

# 2. 创建Linux swapfile
$ mkswap /mnt/swapfile # 可以使用LABLE="SWAP_FILE_LABLE"来指定卷标
Setting up swapspace version 1, size = 3.9 GiB (4194299904 bytes)
no label, UUID=6bd404bf-620e-432a-9544-7e09081496fe

# 3. 激活swap文件,到这里已经可以使用了
$ swapon /mnt/swapfile

# 4. 验证启用情况,-m表示以MB为单位
$ free -m
total used free shared buff/cache available
Mem: 3782 1564 119 95 2098 1849
Swap: 3999 0 3999

但是下次开机又没有了,所以需要写入​​/etc/fstab​​文件,其中包括文件的名字和swap类型:

# 写入/etc/fstab
echo "/mnt/swapfile swap swap defaults 0 0" >> /etc/fstab

校验下swap文件是否加上

$ swapon -s

删除类似于磁盘的

# 1. 取消swapfile
$ swapoff /mnt/swapfile
# 2. 编辑/etc/fstab文件,去掉此swap文件对应记录
# 3. 删除该swapfile
$ rm /mnt/swapfile

5. 文件系统

文件系统是需要OS内核操作的。

格式化的过程是创建文件系统,EXT4将4096字节(4KB)作为一个block。挂载是给磁盘找到一个入口。

每个磁盘分区都是一个文件系统,在Linux中最后都挂载到根目录​​/​​下。

文件系统分类

  • Windows:FAT16,FAT32,NTFS,CIFS(网络),光盘:ISO9660
  • Linux: VFAT,EXT2,EXT3,EXT4(索引型文件系统),XFS,reiserfs,jfs,jfs2,nfs(网络),ocfs(集群),gfs2
  • Linux为了支持众多的文件系统类型,对其又进行了一次封装,称为VFS(Virtual File System),对应用程序提供统一接口来管理文件。

EXT2和EXT3+的区别:

  • EXT3/EXT4也叫做日志文件系统(journal file system)。磁盘分为了:元数据区、数据区和日志区。修复文件的时候需要查找日志区,缩减了开机检查时间,但是需要多读多写一次inode到日志区。
  • EXT2的完整性不高,但是速度很快。

5.1 Linux文件系统重要概念

首先声明,下面是EXT类型的文件系统,是Linux常用的文件系统,不同的文件系统类型,管理方式有所不同。

5.1.1 块

Linux OS存储数据的时候,分开存储块的可用性和块内容,每个块4KB。块的可用性使用**块位图(bitmap)**标识,1为占用,0为可用。块​​block​​是具体存储信息的,而索引是如何快速找到空闲块(可用块)及已占用的块(不可用块),块是最基本的存储单位,一个块是4KB,10KB的文件占用的是3个块,而不能用的2KB不能被其他文件信息占用,这也就产生了文件碎片。

5.1.2 inode

文件的元数据和文件的内容分开存放。文件的元数据存储在inode(index node,索引节点),占用128字节,有一个唯一的inode编号,引用一个文件,有对应的属主属组,文件权限,时间戳,连接数,文件大小(一个文件系统会指明单个文件最大的大小。),所在块数量和编号,但是没有文件名。inode的可用性使用inode位图进行管理。Linux中目录也是一个文件,存储inode号以及对应的文件名,每一条称为一个​​d-entry​​​,创建文件和删除文件都相当于操作​​d-entry​​。

一个EXT4文件系统中可能的inode位图样式:

现在EXT3和EXT4类型的文件系统支持最大16TB,XFS文件系统支持最大100TB。​​mkfs [-t ext4]​​执行过多少次,计算机就有多少个文件系统。

# 查看文件的inode编号
$ ls -li 1
3698361 -rw-rw-r-- 1 basil basil 12769 1227 17:29 1

​df -i​​可以查看inode的总数量、已经使用的数量以及未使用的数量。如果inode使用完毕了,则将不能继续在该磁盘创建文件。但是只要磁盘还有空间(block),仍然可以向其中写入数据,如果block被占用完了,inode也占用完了,则不能继续向该磁盘写入数据。

5.1.3 超级块和块组

磁盘管理中,把一个分区继续划分为block group块组,然后Super Block存储这些块组的基本信息元数据。Super Block是索引和块的结合体,代表的是block和inode的总量:未使用的与已使用的inode和block数量。举例就是超市门口的储物柜,索引就是显示器给配发的小条,箱子就是块,而一整套储物柜就是一个superblock。块组描述符表用来存储块组的信息。

每个分区第一个块(编号为0),预留出来作为Boot Block引导块,多系统共存的时候有必要用到,被MBR中的Boot Loader调用,各自引导不同系统启动。后续块进行划分为块组。如下格式存储:

  • Super Block不一定每个块组都有,需要备份,但是不需要所有块组都备份
  • GDT: Group Description Table,块组描述符表,存储块组信息,需要备份

5.2 相关操作

5.2.1 创建文件系统

创建文件系统的命令有:​​mke2fs​​​,​​mkfs​​​,​​mkfs.ext4​​​。其中​​mkfs.ext4 == mkfs -t ext4​​。

  1. ​mke2fs​
$ mke2fs [option] [/dev/sdb1]              # 专门管理EXT类型的文件系统。
# -j创建EXT3+类型的文件系统
# -b指定块大小,默认为4096,可用取值1024、2048或4096
# -L指定卷标,即分区名称
# -m指定为超级用户保留的区块大小的百分比,不需要写%,默认是5%
# -i指定多少个字节一个inode,默认是8192bytes/inode
# -N指定总共可创建的inode个数
# -F指定强制创建文件系统
# -E用户指定额外文件系统属性
  1. ​mkfs​
# make file system extend4
# 创建 文件系统 扩展系统:是文件系统的类型
# /dev/sdb1 第2块串口硬盘的第一个分区准备格式化了
# $ mkfs.ext4 /dev/sdb1
$ mkfs -t ext4 /dev/sdb1 # 和上一条命令一样,只是-t指定类型

5.2.1 文件系统信息

  1. 查看创建好的文件系统
$ blkid [/dev/sdb]                    # 查询文件系统的属性
# UUID
# TYPE
# LABEL
/dev/sda5: UUID="5938cf13-d43f-4f50-bdbe-3b8349413419" TYPE="ext4" PARTUUID="1a370aa8-6503-ae4c-b0ab-16498612443c"

$ e2label [/dev/sdb] [lable name] # 查看或者定义卷标
  1. 文件系统的相关属性
$ tune2fs /dev/sda5                    # 调整文件系统的相关属性,不需要重新格式化
# -j:不损害原有数据,将ext2升级为ext3,反过来降级不行
# -L LABEL:设定卷标label
# -m #:调整预留给超级用户的百分比
# -r #:指定预留块数
# -o:设定默认挂载选项,常用的是acl
# -c #:设定多少次挂载后自检,0或-1表示关闭此功能
# -i #:每挂载多少天后自检,0或-1表示关闭此功能
# -l: 显示超级块中的信息
# -C:

$ dumpe2fs /dev/sda5 # 显示文件属性信息
# -h:只显示超级块信息

5.2.3 修复文件系统

:warning:下述命令有些适用于CentOS 6,有些适用于CentOS 7,不同的类型系统命令可能不同。

$ fsck /dev/sda5                    # 检查并修复文件系统
# -t:FS_TYPE:指定文件系统,千万不要指定错了,不指定系统会自动检测。
# -a:自动修复,不会询问

$ e2fsck /dev/sda5 # 专门修复EXT文件系统
# -p:自动修复
# -f:强制检测

5.3 文件链接

5.3.1 软链接(符号链接)

symbol link,符号链接,类似于Windows中的快捷方式。在​​d-entry​​中存储的不是文件名和inode,而是文件名和另一个文件路径。需要根据此路径再查找文件。

$ ln -s /src/path  /dst/path               # -s代表的是符号链接
root@basil-2020:/home/basil# ll /proc/1/fd # 下面只看标准的输入输出
lrwx------ 1 root root 64 18 09:30 0 -> /dev/null # 标准输入
lrwx------ 1 root root 64 18 09:30 1 -> /dev/null # 标准输出
lrwx------ 1 root root 64 18 09:30 2 -> /dev/null # 标准错误输出

这里权限之前的​​l​​代表的就是这是一个链接文件。

修改源文件,查看符号链接文件也随之而改变,修改符号链接文件,源文件也被修改(其实本来就是一个文件)。

删除符号链接不影响源文件,删除源文件,符号链接也将失去作用。

软链接可以跨分区(文件系统)。

软链接不影响链接数,就是​​ll​​中第2列。

软链接可以对文件和目录做软链接。

其大小指定的是路径所包含的字符个数。

其权限和最终要访问的文件权限不一定一致,最终访问权限取决于最终文件的权限。

5.3.2 硬链接

指向同样的inode编号的不同文件路径。

$ ln /src/path /dst/path                # 和符号链接只差一个 -s

硬链接不能跨分区,只能在同一分区做硬链接。

硬链接会修改链接数。只有当链接数为1并且再次删除的时候才能完全删除该文件。

硬链接不能对目录来做,只能对文件做。

子目录数越多,硬链接越多。

6. RAID(廉价磁盘冗余阵列)

6.1 简介

RAID,Redundant Array of Independent Disks,用于容错和提升读写速度。级别仅代表磁盘组织方式不同,没有上下之分。

RAID0,RAID0是条带集,需要2块磁盘以上,主要用于读写速率快100%*N,就是可以并发写入。但是不能容错。(不重要的数据

RAID1,俗称镜像卷或者镜像集,只需要两块硬盘(最好是容量一致),读性能上升(可以交替读),写性能下降,同时写入相同数据,最终空间利用率是50%,读写速率一般,主要是为了容错。(操作系统

RAID2

RAID3

RAID4

RAID5,带有奇偶校验。至少三块硬盘(最好容量一致),N块硬盘只有(N-1)块存储具体数据,另一块用于存储奇偶校验和(另外一般还有一块硬盘作为热备盘)。坏一块可以找到出错的数据并恢复,两块坏就恢复不了了。空间利用率是(N-1)/N,读写性能都有提升,也用于容错。(重要数据

10:
性能表现:读、写提升
冗余能力:有
空间利用率:1/2
至少需要4块

01:
性能表现:读、写提升
冗余能力:有
空间利用率:1/2
至少需要4块

50:

​ 性能表现:读、写提升
​ 冗余能力:有
​ 空间利用率:(n-2)/n
​ 至少需要6块

jbod:
​ 性能表现:无提升
​ 冗余能力:无
​ 空间利用率:100%
​ 至少需要2块

6.2 不同场景

  • 硬RAID:需要RAID卡,有自己的CPU,处理速度快,有电池和无电池。
  • 软RAID:通过操作系统实现,例如Windows、Linux。是逻辑RAID,md代表multi disks。尽量减少使用

​mdadm​​模式化的命令

  • 创建模式
  • -C,后面的专用选项
  • -l:级别
  • -n #: 设备个数
  • -a {yes|no}: 是否自动为其创建设备文件
  • -c: CHUNK大小, 2^n,默认为64K
  • -x #: 指定空闲盘个数
  • 管理模式
  • --add, --remove, --fail
  • ​mdadm /dev/md# --fail /dev/sda7​
  • 监控模式
  • -F
  • 增长模式
  • -G
  • 装配模式
  • -A

​cat /proc/mdstat​​查看RAID信息。

# 创建RAID,支持将任何块设备作为RAID
# 创建 RAID名字 级别 RAID数量 热备数量 要使用的磁盘
# mdadm -C(reate) RAID名字 -l(evel) -n(umber) 热备数量 要使用的磁盘,也可以分开写出/dev/sdb, /dev/sdc, /dev/sdd, /dev/sde
# 需要将磁盘分区指定为fd类型,即Linux raid autodetect,fdisk时使用t和L。
$ mdadm -C /dev/md0 -l5 -n3 -x1 /dev/sd{b,c,d,e}
# 格式化(创建文件系统)
$ mkfs.ext4 /dev/md0
# 挂载
$ mount /dev/md0 /mnt/raid5
# 验证,如果使用的4块磁盘都是相同1G的数量,这里就只会看到只有2G可用,因为1G奇偶校验,1G热备。
$ df -hT
# 查看
# -D(etail),查看详细信息
$ mdadm -D /dev/md0
/dev/md0:
Version: 1.2
Creation Time: Mon Feb 24 11:56:42 2020
Raid Level: raid5
Array Size: 2095104 (2046.00 MiB 2145.39 MB)
Used Dev Size: 1047552 (1023.00 MiB 1072.69 MB)
Raid Devices: 3
Total Devices: 4
Persistence: Superblock is persistent

Update Time: Mon Feb 24 11:59:14 2020
State: clean
Active Devices: 3
Working Devices: 4
Failed Devices: 0
Spare Devices: 1

Layout: left-symmetric
Chunk Size: 512K

Consistency Policy: resync

Name: localhost.localdomain:0 (local to host localhost. localdomain)
UUID: 96105589:ef4bbbf2:8efa4eac:ab2240e4
Events: 18
Number Major Minor RaidDevice State
0 8 16 0 active sync /dev/sdb # 数据组
1 8 16 1 active sync /dev/sdc # 数据组
4 8 16 2 active sync /dev/sdd # 数据组

3 8 64 - spare /dev/sde # 热备组

强制移除磁盘:​​mdadm /dev/md0 -f /dev/sdb -r /dev/sdb​

参考资料

  1. ​inode structure in EXT4 filesystem​