一、 磁盘基础
1. 机械硬盘基础
- 磁头:用来在每个盘片上读取数据
- 盘片:通过一个马达带动做同心旋转,双面都可以存储数据,硬盘中可以有多个盘片
- 磁道:track,用来存储数据,在每个盘片上都会划分,形状为圆形,一个盘片可以划分出多个同心圆
- 柱面:cylinder,在不同盘片上,相同编号的磁道组成的逻辑柱状空间,分区是按照柱面分的,最外圈的柱面单位时间内所能读取的数据也是最多的
- 扇区:secotr,每个盘片上扇形空间
2. 磁盘接口类型
IDE
:并口,早期个人桌面应用SCSI
:并口,IDE接口不适用于I/O频率较高的场景,而诞生了SCSI,早期企业级应用的硬盘接口SATA
:串口,现阶段用于个人桌面SAS
:串口的SCSI技术
3. 命名方式
/dev/hd[a-z]
:IDE硬盘,centos 6后就不加区别了,统称为sd开头/dev/sd[a-z]
:SCSI、SATA、USB、SAS
4. MBR
Master Boot Record,主引导记录,用于记录磁盘磁道、柱面、扇区的划分方式。通常被分配在0磁道的0扇区。共512字节
- 前446字节:用来存放操作系统的加载程序,我们称为Bootloader
- 中64字节:存放分区表,每16字节标识一个分区,最多支持4个分区,而现如今磁盘空间越来越大,如果依旧使用4个分区显然已不能满足需求,为解决MBR天生只支持4个分区的问题,诞生了GPT,最多支持128个分区
- 最后2字节:标识当前mbr区域是否有效,一般55AA表示有效
注:扩展分区,因4个分区不够使用,所以可以将一个原本存储主分区表信息的空间指向磁盘上的一段空间,利用新指向的空间来划分区,那么存储指向信息的主分区就叫做扩展分区,而在被指向的空间中划分出来的分区,就叫做逻辑分区
二、 文件系统
1. 文件系统功用
用来按照特定的组织结构来存取数据,通过高级格式化实现,用来在磁盘分区中区分出元数据及数据的存储区域
2. 文件系统的组成(用ext系列文件系统说明)
为了便于管理,ext文件系统首先把磁盘空间分成若干个块组,接着在每个块组中划分出元数据区和数据区,元数据区和数据区都是由若干个小的磁盘块组成
下面是基于单个块组的介绍
2.1 元数据区
元数据是由Inode(索引节点)、inode table(inode表)、位图索引(位图)、块索引(位图)、数据指针
2.1.1 Inode(Index Node | 索引节点)
按照特定格式组织,用来存储单个文件的存放位置、大小、时间戳、权限、属主、属组等属性信息的空间,这个条目就称之为一个Inode(一个索引节点),如果需要访问数据,我们就必须先找到这个文件的Inode,在Inode中提取出这个文件的元数据信息,而后才可以访问
2.1.2 数据地址指针
数据地址指针是用来标识某个文件存储在哪些磁盘块当中。单个文件的大小取决于一个inode可以指向(引用)多少个磁盘块,为了能兼容更大的文件,ext文件系统就引入多级数据地址指针的概念,使得其可以兼容更大的单个文件,有直接指针、间接指针、三级指针之分,多级指针的概念很类似于扩展分区中指向逻辑分区的概念
2.1.3 索引位图 (inode bitmap)
假如新建一个文件,我们首先需要在Inode中找到一条空闲Inode,再分配使用,但这种方式效率太低了。可以利用一段空间专门存放Inode空闲的情况,这个条目就叫位图索引
2.1.4 块位图
类似索引位图,只是它是用来标识磁盘块的空闲情况的
2.1.5 inode table
存储inode条目的表格
2.2 数据区
2.2.1 块组描述符
用来描述本块组的大小、数据校验码、本块组Inode表的存储位置、位图索引的存放位置、空闲的块和inode、可用的数据块和可用的Inode条目的位置
2.2.2 超级块
用来描述整个文件系统的逻辑架构,里面定义了一共有多少个块组、每个块组的大小、文件系统的卷标、UUID、文件系统的特性、空闲磁盘块数、空闲Inode数等一些关于文件系统的信息,超级块自己也在块组中的某个磁盘块中存储,并且会在不同的块组中存储多份
2.2.3 磁盘块
专门用来存储数据的空间
2.3 日志区
无日志区的情况下,如果文件数据在存储过程中出现断电等异常情况,开机后,要想知道哪些文件没存完只能全盘扫描,对于容量很大的盘,需要的时间也会很长。如果有了日志区,在文件存储过程中,首先把文件的元数据存储在日志区中,如果这时出现断电,下次开机仅用查看日志区的内容就可以知道哪些文件没有存完。不过日志区也是有缺点的,因为任何文件的元数据在存储时都先存储到日志区,等全部数据存储完毕后,再将日志区的数据挪动到元数据区,这样就会带来一次额外的I/O操作的,它对比非日志文件系统的性能一定会有所下降的,不过对于今天的磁盘性能,这种差别都是微乎其微的,但它带来的好处却是显而易见的,所以设置日志区还是很有必要的
2.4 预留空间
在数据区会预留一些空间,用于在数据区数据存放满了的时候,管理员可以使用这些地方来挪动文件
3. 一次完整的文件查找过程
假设寻找文件/var/log/messages
- 首先,找到
/
的Inode元数据,从/
元数据中提取出/
的数据指针,接着根据指向查找磁盘块,在磁盘块中,一定会记录着/var
的目录名称和与之对应的Inode编号,从中提取出/var
目录的inode编号 - 拿到
/var
目录的Inode编号后,从元数据区找到这条Inode条目,提取出数据指针,接着根据指针指向去查找存储着/var
目录信息的磁盘块,其中一定有log/
目录的Inode编号 - 取得
log/
的Inode编号,在元数据区中取得log/
对应的数据块,从数据块中可找到message/
的Inode编号,最后通过message/
的inode条目,获取message/
的数据块存放位置,就可以查看message/
的数据了
注:其实目录也是一个文件,但它仅仅存放着通过这个目录能直接找到的文件和与之对应的Inode编号(父目录不存储子目录中文件的Inode编号,只存放直接能找到的文件的Inode编号),在内核查找文件的过程中,目录的作用就像一个路标,需要根据指向来回多次的才能找到最终数据,所以对于经常访问的数据,就可以将它缓存在内存中来加速访问,这就是buffer/cache
的意义
4. 格式化种类
假如把磁盘空间比作一个图书馆,那么格式化就是在屋子里摆上书架,并准备好一本册子用来做索引的过程
- 低级格式化:一般是在厂商出厂时进行的,用来划分磁道,行程簇等
- 高级格式化:分区之后进行,创建文件系统
5. 交换分区
程序员在编程时不能预知用户的内存资源,但又想充分利用用户的内存资源,所以linux就虚拟出一个内存空间告诉进程随便用,一旦物理内存满了,内核就会根据lru算法(最近最少使用算法)将有些进程挪到硬盘上的交换分区去。交换分区配额对不同的应用要求是各不相同的,如果跑的应用的Oracle或MySql这样的数据库,一旦使用了交换分区,那么它的性能是急剧下降的,对于这种应用交换分区分配1G或512MB就可以了,因为这种应用如果想跑的顺畅,那么就要提供充足的物理内存。如果跑的应用是科学计算、批处理的类似Hadoop这样的应用,对于内存量要求很大,但是对于性能要求不是很高,就可以使用大一些的交换分区。早期时候物理内存较小的时候如128MB、512MB,使用的交换分区大小是遵循物理内存的1.5倍到2倍,不过现在服务器内存动辄8G、16G,已经不太适用了,具体还是根据实际需求分配
6. 常见的文件系统
- ext系列:ext2、ext3、ext4
- xfs:centos7默认采用的文件系统
- btrfs:
- reiserfs:因作者入狱,后来没人维护了
- iso9660:光盘的文件系统
- 网络文件系统:nfs,cifs
- 集群文件系统:gfs2、ocfs2
- 内核级分布式文件系统:ceph
- windows:vfat、ntfs
- 伪文件系统:proc、sysfs、tmpfs、hugepagefs
- Unix文件系统:UFS、FFS、jfs(日志文件系统)
- 用户空间的分布式文件系统:mogilefs、moosefs、glusterfs
- vfs:虚拟文件系统,程序员开发程序时,不能预知用户的文件系统,为了不增加程序员的开发负担,就把底层各种类型的文件系统类型向上统一为vfs,由它解决底层的文件系统不统一问题
(8) 文件系统相关的配置文件:
- /proc/filesystems:可查看当前系统支持的文件系统类型
- /etc/mtab:追踪当前系统的所有挂载和卸载,mount命令查看的文件
- /proc/mounts:内核真正识别到的mount的分区
- /proc/partations
注:任何类型的文件系统如果想使用,那么必须事先加载它的模块,可使用lsmod查看
三、 文件系统管理工具
1. fdisk
提供了一个交互式接口管理分区,有许多子命令,分别用于不用的管理功能,所有操作均在内存中完成,不会直接保存在磁盘上,直到使用w保存才会生效,最能可管理15个分区信息
命令格式:fdisk [DEVICES]
交互式管理接口菜单选项
- m
:查看使用帮助
- l
:列出所有分区ID
- d
:删除指定分区信息
- p
:显示分区信息
- t
:改变分区类型
- n
:创建新的分区
- w
:保存分区
- q
:退出
使用fdiks -l /dev/sdba,反馈的信息 (Centos 7)
Disk /dev/sda: 107.4 GB, 107374182400 bytes, 209715200 sectors # 磁盘的名称、大小、字节、扇区
Units = sectors of 1 * 512 = 512 bytes #
Sector size (logical/physical): 512 bytes / 512 bytes #扇区的逻辑大小/物理大小
I/O size (minimum/optimal): 512 bytes / 512 bytes #I/o传输的最佳值
Disk label type: dos #磁盘标签类型
Disk identifier: 0x000b2053
Device Boot Start End Blocks Id System #Boot有*标识为可引导分区,意为其中有内核
/dev/sda1 * 2048 2099199 1048576 83 Linux #start/end:起始扇区/结束扇区
/dev/sda2 2099200 209715199 103808000 8e Linux LVM #block:包含的磁盘块数
#id:分区标识
注:分区分好后,如果没有显示分区,需要使用命令使内核重读分区表,partx -a [DEV]
2. mkfs类
命令格式:
用法一:mkfs.fs_type [option] /dev/
用法二:mkfs -t fs_type [option] /dev/
option:
-L 'LABEL':加卷标
-f:强制格式化
3. mke2fs
ext系列的文件系统的专用工具,mke2fs -t [option] {ext2|ext3|ext4}
[option]
-b {1024|2048|4096}:指定块大小
-L ‘label’:指定卷标
-j:相当于使用 -t ext3
-i #:为数据空间每多少个字节创建一个inode,此大小不应该小于块大小
-N #:为数据空间#个inode
-m #:为管理人员预留的空间占据的百分比
-O feature[,…]:创建此分区时启用指定特性
-O ^feature:创建此分区时关闭指定特性
4. mkswap命令:
-
格式
mkswap [option] /dev/
option -L 'label':指定卷标
NOTE:格式化交换分区要先调整分区类型为82(交换分区)
-
启用交换分区:
swapon [option] [device]
option -a:激活所有分区 -p #:指明优先级,如果有性能好的swap,应该把其优先级提升,如果性能相同的话也可以设置相同优先级,使其负载均衡, 需要注意的是,如果两个swap分区在同一个硬盘样,那负载均衡就没有意义了
-
禁用:
swapoff [option] [device]
5. e2label
ext系列文件系统的专用命令,格式:e2label dev [label]
label:省略为查看,指定为设置
6. tune2fs
重新设定ext系列文件系统可调整参数的值
格式:tune2fs [option] /dev
option
-l:查看指定文件系统的超级块信息
-L 'label':修改卷标
-m #:修改预留空间的百分比
-j:将ext2升级为ext4
-O:文件系统属性的打开或禁用
-U uuid:修改uuid
7. dumpe2fs
格式:dump2fs [option] /dev/
-h:查看超级块信息
8. blkid
格式:blkid [option] /dev/
[option]:
-U 'uuid':根据uuid查找设备
-L 'label':根据卷标查找设备
9. fsck:文件系统检测命令
用法一:fsck.fs_type [option]
用法二:fsck -t fs_type [option]
option:
-a:自动修复错误
-r:交互式修复错误
10. e2fsck:ext系列文件系统专用工具
格式:e2fsck [option] /dev/
option:
-y:自动回答为yes
-f:强制修复
四、 挂载
1. 挂载的意义
将额外文件系统与根文件系统的某目录建立关联关系,进而使得此目录可作为其它文件访问入口的操作,我们称之为挂载。解除此关系称为卸载
2. 命令
格式:mount [option] [-o option] /dev/ dir
option:命令选项
-t vfs_type:指明要挂载设备上的文件系统类型,可省略
-r:只读挂载
-w:读写挂载
-n:默认挂载或卸载会更新/etc/mtab,这个选项不更新/etc/mtab
-a:自动挂载定义在/etc/fstab中的所有文件系统,但是需要文件系统特性中包含自动挂载
-v:显示详细信息
-L ‘label’:基于卷标的方式挂载
-U ‘uuid’:基于uuid挂载
-B:可将系统上的两个目录进行绑定,如果有些程序文件就需要在特定目录中访问文件,但是需要的文件又不在这个目录中,
就需要用到这个命令,例如mount /etc /mnt,意为把/etc绑定到/mnt,以后访问/mnt就是访问/etc
-o option:指明文件系统挂载时启用的特性,可支持多选项,用逗号分隔
async:异步I/O,将修改后的数据先存储在内存中,就向进程反馈已经存储完毕,在由内核决定合适时间将修改后的数据回存至磁盘,
如果在未回存之前出现断 电情况,则内存中修改完毕的数据会丢失,但好处为会提升磁盘I\O
sync:同步模式,意为不使用异步模式,数据安全性高,但性能差
atime:每一次都更新访问时间戳,包含目录
noatime:不更新访问时间戳,包含目录
diratime、nodiratime:仅对目录有效
auto、noauto:是否支持自动挂载
exec、noexec:是否支持将文件系统上的应用程序运行为进程,一般对不信任的文件系统可使用noexec,使此硬盘上的进程无法运行
dev、nodev:如果需要挂载的文件系统中存在设备文件,此选项就可设定此文件系统中的设备文件是否可用。
suid、nosuid:是否支持suid
remount:重新挂载
ro:只读
rw:读写
user、nouser:是否允许普通用户挂载此设备
acl:启用此设备的facl功能
compress={lzo|zlib}:启用压缩,centos上支持的新特性
defaults:默认挂载选项rw, suid, dev, exec, auto, nouser, and async
3. 配置文件:/etc/fstab的六个字段
- 要挂载的设备或伪文件系统
- 设备文件
- LABEL:
LABEL=""
- UUID:
UUID=""
- 伪文件系统
- 挂载点:如果要挂载,它的挂载点就叫swap
- 文件系统类型
- 挂载选项
- 转储频率:多长时间备份一次
0:表示不做转储
1:每天转储一次
2:每隔一天转储 - 自检次序:系统非法关机后,自检的顺序
0:不自检
1:首先自检,一般只有rootfs才用1
2:1自检完在自检
4. 挂载光盘设备
- 接口
- IDE:/dev/hdc
- SATA:/dev/sr0
- 链接文件:
- /dev/cdrom
- /dev/cdrw
- /dev/dvd
- /dev/dvdrw
5. 卸载
- 命令:umount
- 查看哪个用户正在访问设备:
fuser -v mount_dir
lsof mount_dir
fuser -km mount_dir
:强行T掉正在访问此设备的进程。
五、链接
1. 硬链接
- 文件数据查找其实就是多次查找Inode指向的数据,如果让多个路径都指向同一个Inode,那么就能通过多个路径找到这些数据,并且每次添加一个路径,这个Inode的引用计数就会加1,删除其中的任何一个文件都不会影响数据,因为还有另一个路径可以找到这些数据
- 不能跨分区进行:因为不能保证A分区上引用的B分区是否已经挂载。第二点,应该是因为A、B分区Inode属于自治的,可能会出现重复,所以不能引用
- 不能够对目录使用:因为对目录使用的话,可能会引起循环引用,但是系统中其实是有目录的硬链接的,是目录的自引用,分别是
.
和..
2. 软链接
- 当通过软链接访问数据时,在此软连接的基名对应的Inode条目中,不会指向任何的磁盘块,而是在其中保存源文件的路径,接着在根据这个路径再去寻找源文件。所以,当源文件删除的时候,这个软链接也就失效了。软连接的大小为其指向的路径字符串的字节数,不增加或减少目标文件inode的引用计数
- 可以对目录进行,可以跨分区
3. 命令
格式:ln [option] src_link dest_link
-s:创建软链接
-v:显示过程
4. 特殊文件的元数据
- 链接文件的元数据:存储数据指针的空间当中,存储的是真实文件的访问路径
- 设备文件:存放数据指针的空间当中,存储的是设备的主、次设备号,同样没用占据真正的数据块
六、 空间信息查看命令
1. free命令
查看内存空间的使用情况
格式:free [option]
option
-m:以MB为单位
-g:以GB为单位
-s #:每隔#秒刷新显示一次
free命令输出信息解释
[root@node1 ~]# free -m
total used free shared buff/cache available
Mem: 1737 305 357 2 1074 1247
Swap: 0 0 0
total:总大小 | used:已用空间 | free:空闲空间 | shared:共享内存空间 |
buff/cache: 缓冲和缓存的占用信息 | available:实际可用空间
自己对free和available的区别理解(网上找的)
free大小 = total - used - shared - buff/cache
available大小 = total - used - shared
available大小为什么和free不一样呢:linux内核拿了一部分内存空间作为buffer/cache使用,
但当物理内存不够用的时候,就可以把buff/cache占用的空间清出去,给其他进程使用。
available就是清了buffer/cache的大小。所以,通俗的讲就是:确实现在可用内存的还剩357M了,
但是你要真想用,我可以个你挪地方,把buff/cache占的地方给你使。
2. df命令
格式:df [option]
optins:
-h:人类易读的方式显示
-i:显示inode使用情况,可结合空间使用情况进行对比,查看inode设定是否合理
-P:以posix兼容的格式输出,意为无论路径多长,都输出在一行,如果不使用此选项,
遇到文件系统名称或挂载路径过长时,可能会自动换行显示,不便于awk、grep等文本过滤工具采集数据
-l:仅显示本地文件系统
3. du命令
统计目录占用大小
格式:du [option] [DIR]
option
-h:人类易读的方式显示
-sh:只显示总大小
4. dd命令
格式:dd if=/PATH/FROM/SRC of=/PATH/TO/DEST bs=# conut=#
七、练习:
1. 创建一个10G的分区,并格式化为ext4文件系统
- block大小为2048,预留空间为2%,卷标为MYDATA
[root@node1 ~]# mkfs.ext4 -b 2048 -m 2 -L 'MYDATA' /dev/sdb1
- 挂载至/mydata目录,要求挂载时禁止程序自动运行,且不更新文件的访问时间戳
[root@node1 ~]# mount -o nodiratime,noexec /dev/sdb1 /mydata [root@node1 ~]# mount /dev/sdb1 on /mydata type ext4 (rw,noexec,nodiratime,relatime,seclabel,data=ordered)
- 可开机自动挂载
[root@node1 ~]# vim /etc/fstab LABEL="MYDATA" / ext4 defaults,noexec,nodirtime 0 0
2. 创建一个大小为1G的swap分区,并启动
1. 使用fdisk命令创建并调整分区类型为82(swap)
/dev/sdb2 20973568 23070719 1048576 82 Linux swap / Solaris
2.格式化并启用
[root@node1 ~]# mkswap -L 'swap-1G' /dev/sdb2
Setting up swapspace version 1, size = 1048572 KiB
LABEL=swap-1G, UUID=7ffae958-c311-4e06-a35f-54f9b9d937dc
[root@node1 ~]# swapon /dev/sdb2
[root@node1 ~]# vim /etc/fstab
LABEL='swap_1G' swap swap defaults 0 0
3. 创建一个20G的文件系统,块大小为2048,文件系统ext4,卷标为TEST,要求此分区开机后自动挂载至/testing目录,且默认有acl挂载选项
[root@node1 ~]# mkfs.ext4 -L 'TEST' -b 2048 /dev/sdb3
[root@node1 ~]# vim /etc/fatab
LABEL='TEST' /testing ext4 defaults,acl 0 0
4. 创建一个5G的文件系统,卷标HUGE,要求此分区开机自动挂载至/mogdata目录,文件系统类型为ext3
[root@node1 ~]# mkfs.ext3 -L 'HUGE' /dev/sdb5
[root@node1 ~]# vim /etc/fstab
LABEL='HUGE' /mogdata ext3 defaults 0 0
5. 写一个脚本
- 列出当前系统识别到的所有磁盘设备
- 如磁盘数量为1,则显示其空间使用信息,否则显示最后一个磁盘上的空间使用信息
#!/bin/bash
#
######### all disk list
disk_Count=$(fdisk -l | grep '^Disk[[:space:]]/dev/s' --color=never | wc -l | cut -d' ' -f 1)
echo && echo "You have $disk_Count disk."
fdisk -l | grep '^Disk[[:space:]]/dev/s'
######## disk info
echo
if [ $disk_Count -eq 1 ]; then
df -h | head -n 1
disk_Name=$(fdisk -l | grep '^Disk[[:space:]]/dev/s' --color=never | cut -d' ' -f 2 | cut -d: -f 1)
df -h | grep "$disk_Name" --color=never
else
df -h | head -n 1
disk_Name=$(fdisk -l | grep '^Disk[[:space:]]/dev/s' --color=never | tail -n 1 | cut -d' ' -f 2 | cut -d: -f 1)
df -h | grep "$disk_Name" --color=never
fi