磁盘存储和文件系统详解
1、磁盘结构
设备文件:关联至一个设备驱动程序,进而能够与之对应硬件设备进行通信
I/O Ports:I/O 设备地址
一切皆文件:open(),read(),write(),close()
设备类型:
块设备:block,存取单位 “块”,磁盘,支持缓存
字符设备:char,存取单位 “字符”,键盘
设备号码:
主设备号:major number,标识设备类型
次设备号:minor number,表示同一类型下的不同设备
磁盘设备的设备文件命名:/dev/dev_file
SCSI,SATA,SAS,IDE,USB:/dev/sd
虚拟磁盘:/dev/vd(kvm 技术)、/dev/xvd(xen 技术)
不同磁盘标识:a-z,aa,bb…
/dev/sda,/dev/sdb…同一设备上的不同分区:1,2…
/dev/sda1,/dev/sda5
硬盘存储术语:
head:磁头
track:磁道
cylinder:柱面
sector:扇区
# 1 为机械硬盘、0 为固态硬盘(针对于直接在物理机上装的 Linux 可以测,虚拟机没用) cat /sys/block/sda/queue/rotational
硬盘存放单位:CHS(磁盘三围)
每个盘片对应一个磁头(head),每个盘片被化成多个同心圆(track/cylinder),每个同心圆被切断成多个扇区(sector)。磁盘存储最小单位是 sector。
采用 24bit 位寻址,其中前10位表示 cylinder(柱面),中间8位表示 head(磁头),后面6位表示 sector(扇区),最大寻址空间8GB。
LBA ( logical block addressing )
LBA 是一个整数,通过转换成 CHS 格式完成磁盘具体寻址。
ATA-1 规范中定义了28位寻址模式,以每扇区512位组来计算,ATA-1 所定义的28位 LBA 上限达到128 GiB。2002年 ATA-6 规范采用48位 LBA,同样以每扇区512位组计算容量上限可达128 Petabytes。
由于 CHS 寻址方式的寻址空间在大概8GB以内,所以在磁盘容量小于大概8GB时,可以使用 CHS 寻址方式或是 LBA 寻址方式,在磁盘容量大于大概8GB时,则只能使用LBA寻址方式。
2、 MBR 和 GPT 分区管理
2.1 为什么分区
优化 I/O 性能、实现磁盘空间配额限制、提高修复速度、隔离系统和程序、安装多个 OS、采用不同文件系统
2.2 分区
两种分区方式:MBR,GPT
MBR:Master Boot Record 主引导记录,1982 年,使用 32 位表示扇区数,分区不超过2T
如何分区:按柱面
0 磁道 0 扇区:512bytes,不属于任何分区(存取分区元数据)
446bytes:boot loader(主引导程序)
64bytes:分区表,其中每 16bytes 标识一个分区
2bytes:55AA(标记位),没有 55AA 标记位,认为没有分区
MBR 分区中一块硬盘最多有 4 个主分区,也可以 3 主分区 + 1 扩展(N 个逻辑分区)
hexdump -C -n 512 /dev/sda # 查看 sda 硬盘的前 512 字节
MBR 分区结构:
硬盘主引导记录 MBR 由 4 个部分组成:
主引|导程序,偏移地址 0000H--0088H , 它负责从活动分区中装载,并运行系统引导程序;
出错信息数据区,偏移地址 0089H--00E1H 为出错信息,00E2H--01BDH 全为 0 字节;
分区表(DPT,Disk Partitioln Table)含 4 个分区项,偏移地址 01BEH--01FDH,每个分区表项长 16 个字节,共 64 字节为分区项 1、分区项 2、 分区项 3、分区项 4;
结束标志字,偏移地址 01FE--01FF 的 2 个字节值为结束标志 55AA。
备份分区表:
hexdump -C -n 512 /dev/sda # 查看 sda 硬盘的前 512 字节 dd if=/dev/sda of=/data/dpt bs=1 count=66 skip=446 # 备份分区表(skip 表示跳过 if、seek 跳过 of) hexdump -C /data/dpt # 查看备份分区表 dd if=/dev/zero of=/dev/sda bs=1 count=2 seek=510 # 将 55aa 位清空,模拟破坏分区表 hexdump -C -n 512 /dev/sda # 查看 sda 硬盘的前 512 字节,发现已经更改 fdisk -l /dev/sda # 查看硬盘分区信息 lsblk # 查看内存分区表 dd if=/data/dpt of=/dev/sda bs=1 count=2 skip=64 seek=510 # 恢复 55aa 位
GPT 分区:
GPT:GUID ( Globals Unique Identifiers ) partition table 支持 128 个分区,使用 64 位,支持 8Z ( 512Byte/block ) 64Z ( 4096Byte/block )
使用 128 位 UUID(Universally Unique Identifier)表示磁盘和分区 GPT 分区表,自动备份在头和尾两份,并有 CRC 校验位 uuidgen,生成 UUID。
UEFI (Unified Extensible Firmware Interface 统一可扩展固件接口)硬件支持 GPT,使操作系统启动。
BIOS+MBR 和 UEFI+GPT:
2.3 管理分区
列出块设备:lsblk
创建分区使用:
fdisk 创建 MBR 分区
gdisk 创建 GPT 分区
parted 高级分区操作
重新设置内存中的内核分区表版本
Partprobe
添加硬盘,创建分区:
不重启电脑识别新添加的硬盘:echo ‘- - -’ > /sys/class/scsi_host/host2/scan
[root@centos6 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sr0 11:0 1 4.2G 0 rom sda 8:0 0 20G 0 disk [root@centos6 ~]# echo '- - -' > /sys/class/scsi_host/host2/scan # 触发磁盘扫描 [root@centos6 ~]# lsblk # 列出所有可用块设备的信息 NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sr0 11:0 1 4.2G 0 rom sda 8:0 0 20G 0 disk sdb 8:16 0 20G 0 disk
parted 命令:parted 的操作都是实时生效的,小心使用
用法:parted [选项]…[设备 [命令 [参数]…]] parted /dev/sdb mklabel gpt|msdos # 创建 GPT 或 MBR 分区 parted /dev/sdb print # 打印分区表 parted /dev/sdb mkpart primary 1 200(默认 M) # mkpart:分区;primary:全是主分区;起始点和结束点(默认 M) parted /dev/sdb rm 1 # 删除分区 parted -l # 列出分区信息
分区工具 fdisk 和 gdisk,分别为 MBR 和 GPT 格式的分区工具
# 子命令: p 列出分区列表 t 更改分区类型(默认 83,swap 82) n 创建新分区 d 删除分区 v 校验分区 u 转换单位 fdisk -u=cylinders /dev/sdb(更改为以扇区分区) w 保存并退出 q 不保存退出 # 查看分区的方式: cat /proc/partitions lsblk fdisk -l /dev/sdb # 看到的是真正硬盘的分区表,其他三项看的是内存 ll /dev/sdb* 划分分区、更改分区要同步信息到硬盘:(新硬盘分区不会有,旧硬盘更改分区注意 warning) centos6: partx -a /dev/sda # 增加分区 partx -d --nr 6 /dev/sda # 删除分区 centos5,7: partprobe 使用 dd 命令克隆分区表(只能克隆主分区、扩展分区,逻辑分区不能克隆) 使用 dd 命令清空硬盘标记位 数字越小,在越外圈,可以提高优化!
3、 管理文件系统
3.1 文件系统
文件系统是操作系统用于明确存储设备或分区上的文件的方法和数据结构,即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件结构称为文件管理系统,简称文件系统。
从系统角度来看,文件系统是对文件存储设备的空间进行组织和分配,负责文件存储并对存入的文件进行保护和检索的系统。具体地说,它负责为用户建立文件,存入、读出、修改、转储文件,控制文件的存取,安全控制,日志,压缩,加密等。
3.2 Linux 文件系统类型
支持的文件系统: /lib/modules/`uname -r`/kernel/fs df -T # 查看文件系统类型
ext2:适用于那些分区容量不是太大,更新也不频繁的情况,例如 /boot 分区;
ext3:是 ext2 的改进版本,其支持日志功能,能够帮助系统从非正常关机导致的异常中恢复。它通常被用作通用的文件系统;
ext4:是 ext 文件系统的最新版。提供了很多新的特性,包括纳秒级时间戳、创建和使用巨型文件(16TB)、最大 1EB 的文件系统,以及速度的提升;
SGI 的 xfs:支持最大 8EB 的文件系统。
其他文件系统:btrfs ( Oracle ),reiserfs,jfs ( AIX ),swap
光盘:iso9660
Windows:FAT32,exFAT,NTFS
Unix:FFS ( fast ),UFS ( unix ),JFS2
网络文件系统:NFS,CIFS
集群文件系统:GFS2,OCFS2 ( oracle )
分布式文件系统:fastdfs,ceph,moosefs,mogilefs,glusterfs,Lustre
RAW:未经处理或者未经格式化产生的文件系统
3.3 创建文件系统
文件系统分类:
根据是否支持 “journal” 日志功能:
日志型文件系统:ext3,ext4,xfs…
非日志型文件系统:ext2,vfat
文件系统的组成部分:
内核中的模块:ext4,xfs,vfat
用户空间的管理工具:mkfs.ext4,mkfs.xfs,mkfs.vfat
Linux 的虚拟文件系统:VFS
间接的访问各个文件系统
查看支持的文件系统:cat /proc/filesystems
创建文件系统:
mkfs 命令: mkfs.[ext3|ext4|xfs…] /dev/device 例: mkfs.xfs /dev/sdb1 # 将/dev/sdb1 创建为 xfs 的文件系统格式 mkfs -t [ext3|ext4|xfs…] /dev/device -L 'LABEL' # 设定卷标名 blkid /dev/device # 查看文件系统类型
创建 ext 文件系统:
mke2fs:ext 系列文件系统专用管理工具 -t [ext2|ext3|ext4] 指定文件系统类型 -b [1024|2048|4096] 指定块大小为 1K,2K,4K 每创建一个文件不论大小以块为单位分配 -L 'LABEL' 设置卷标名 -f 重新格式化 -j 相当于 -t ext3 mkfs.ext3 = mkfs -t ext3 = mke2fs -j = mke2fs -t ext3 -i 为数据空间中每多少个字节创建一个 inode,不应该小于 block 大小 -N 指定分区中创建多少个 inode -I 一个 inode 记录占用的磁盘空间大小,128—4096 -m 指定为管理员预留的空间,默认为 5% -O FEATURE 启用指定特性 -O ^FEATURE 关闭指定特性 把连续的块组合成组,每个组有自己节点表
文件系统标签:
指向设备的另一种方法,与设备无关 blkid:块设备属性信息查看 -U UUID 根据指定的 UUID 来查找对应的设备 -L LABEL 根据指定的 LABEL 来查找对应的设备 e2label:管理 ext 系列文件系统的 LABEL e2label /dev/device [LABEL] # 指定卷标名 findfs:查找分区 findfs UUID=XXX findfs LABEL=XXX
超级块和 INODE TABLE:
tune2fs:重新设定 ext 系列文件系统可调整参数的值 -l 查看指定文件系统超级块信息;super block -L 'LABEL' 修改卷标名 -m 修改预留给管理员的空间百分比 -j 将 ext2 升级为 ext3 -O 文件系统属性启用或禁用,-O ^has_journal(启用日志) -o 调整文件系统的默认挂载选项,-o ^acl -U UUID 修改 UIID 号(UUID 使用 uuidgen 命令生成) dumpe2fs:显示 ext 文件系统信息,将磁盘分组管理 -h 查看超级块信息,不显示分组信息相当于 tune2fs -l xfs_info:显示已挂载的文件系统信息
文件系统故障常发生于死机或非正常关机,挂载为文件系统标记 "no clean"
注意:一定不要在挂载状态下执行修复!
fsck.FS_TYPE fsck -t FS_TYPE 注意:FS_TYPE 一定要与分区上文件类型相同 -a 自动修复 -r 交互式修复错误 e2fsck:ext 系列文件专用的检测修复工具 -y 自动回答为 yes -f 强制修复 -p 自动进行安全的修复文件系统问题 xfs_repair:xfs 文件系统专用检测修复工具 -f 修复文件,设备不修复 -n 只检查 -d 允许修复只读的挂载设备,在单用户下修复时使用,然后立即 reboot
4、挂载设备
4.1 挂载 mount、卸载 umount
挂载:将额外文件系统与根文件系统某现存的目录建立起关联关系,进而使得目录作为其他文件访问入口的行为
卸载:为解除此关联关系的过程
挂载点下原有文件在挂载完成后会被临时隐藏,挂载点目录一般为空。
伪文件系统名称:proc,sysfs,devtmpfs,configfs
mount device dir device:指明要挂载的设备 dir:挂载点 事先存在,建议使用空目录 进程正在使用的设备无法被卸载 默认挂载可读可写 mount -r:只读挂载 mount -o remount,[rw|ro]:取消挂载 /etc/mtab # 挂载信息实时更新 mount -L 'LACEL' /mnt/sdb1 # 以卷标的方式挂载 mount -U 'UUID' # 以 UUID 挂载 -B 绑定目录到另一个目录上 -t 指明要挂载的设备上的文件系统类型(默认不用写) -r readonly 只读挂载 -w read and write 读写挂载 -n 不更新/etc/mtab,mount 不可见 隐藏挂载,centos7 不支持 -a 自动挂载所有支持自动挂载的设备(定义在了/etc/fstab 文件中,且挂载选项中有 auto 功能) 查看内核追踪到的已挂载的所有设备: cat /proc/mounts 同一挂载点同一时间只能挂载一个;可以将一个设备挂载到多个挂载点。 也可以将文件挂载至文件夹(将文件先格式化成特定的文件系统)centos6 上挂载时要加 -o loop 选项 相当于 U 盘 losetup -a # 显示 loop 设备分配 ls /dev/loop* # 显示 loop 设备 centos 6 只有 0-7 8 个设备,centos7 没限制 mknod /dev/loop100 b 7 100 # 临时创建设备,100 是编号 编辑/boot/grub/grub.conf 文件,再 kernel 后加上 max_loop=100,重启生成 100 个 loop 设备 losetup /dev/loop66 /data/disk # 关联 loop 设备再挂载
4.2 mount 常用选项
-o options : (挂载文件系统的选项),多个选项使用逗号分隔 async异步模式 sync同步模式,内存更改时,同时写磁盘 atime/noatime 包含目录和文件 diratime/nodiratime 目录的访问时间戳 auto/noauto 是否支持自动挂载,是否支持-a选项 exec/noexec 是否支持将文件系统上运行应用程序 dev/nodev 是否支持在此文件系统上使用设备文件 suid/nosuid 是否支持suid和sgid权限 remount 重新挂载 ro只读 rw读写 user/nouser 是否允许普通用户挂载此设备,/etc/fstab 使用 acl 启用此文件系统上的ac|功能 loop 使用loop设备 defaults:相当于rw, suid, dev, exec, auto, nouser, async
4.3 持久挂载和 swap 空间管理
fuser 可以显示出当前哪个程序在使用磁盘上的某个文件、挂载点、甚至网络端口,并给出程序进程的详细信息。
fuser 显示使用指定文件或者文件系统的进程 ID。
# yum install psmisc -y # 安装 fuser # fuser -v /mnt/sdb1 # 查看谁正在使用该文件夹,请进一步了解 fuser 命令的用法 /mnt/sdb1: root kernel mount /mnt/sdb1 root 1245 ..c.. bash # fuser -km /mnt/sdb1 # 强制杀掉该目录使用的用户进程
查看挂载情况:
# findmnt /mnt/sdb1 # df 显示不了隐藏的挂载,使用 findmnt 查询该目录是否为挂载点 # 查看正在访问指定文件系统的进程: # lsof /boot # 也能看到是否有人使用该目录(挂载点) # fuser -v /mnt/sdb1 # 也可以 # 终止所有正在指定的文件系统的进程: # fuser -km /mnt/sdb1
挂载点和 /etc/fstab
配置文件系统体系
被 mount、fsck 和其他程序使用
系统重启时保留文件系统体系
可以在设备栏使用文件系统卷标
文件挂载配置文件:
/etc/fstab 每行定义一个要挂载的文件系统
要挂载的设备或伪文件系统:
设备文件:LABEL:LABEL=卷标名
UUID:UUID=uuid
伪文件系统名称:proc,sysfs
挂载点
文件系统类型:ext4,xfs,iso9660,nfs,none
挂载选项:defaults,acl,bind
使用mount -a命令挂载 /etc/fstab 中的所有文件系统,使配置文件生效
转储频率:0:不做备份 1:每天转储 2:每隔一天转储
fsck 检查的文件系统的顺序:0:不自检 1:首先自检 2:非 rootfs 使用
注意:mount -a 针对于刚挂载的,加载使生效;对于已经挂载的,更改属性值后使用 mount -a 不管用,使用mount -o remount /mnt/sdb1。
处理交换文件和分区:
swap 交换分区是系统 RAM 的补充,swap 分区支持虚拟内存,当没有足够的RAM 保存系统处理的数据时会将数据写入 swap 分区。
当系统缺乏 swap 空间时,内核会因 RAM 内存耗尽而终止进程。配置过多 swap 空间会造成存储设备处于分配状态但闲置,造成浪费,过多 swap 空间还会掩盖内存泄露。
推荐系统 swap 空间:
设置增加 swap 大小,至于磁盘外侧(访问快)
1.新添硬盘,分区 1(于磁盘外侧);分配大小完毕,t 82 设置 swap 格式分区。 2.mkswap /dev/sdc1 # 格式化(swap 格式使用 mkswap 格式化) 3.写入/etc/fatab 文件,swap 挂载到 swap;默认值更改为 pri=10(优先级) 4.swapon -a # 使 swap 格式配置文件生效 5.swapon -s # 相当于 cat /proc/swaps,查看 swap 分区信息 swapoff /dev/sdc1 # 关闭 swapon -a 开启 free -h # 查看内存和 swap 信息 增加文件 swap 分区,dd 设置大文件(swap 只能写文件名),删除的话:关闭,改文件
swap 的优先级:
可以指定 swap 分区0到32767的优先级,值越大优先级越高。
如果用户没有指定,那么核心会自动给 swap 指定一个优先级,这个优先级从-1开始,每加入一个新的没有用户指定优先级的 swap,会给这个优先级减一。
先添加的 swap 的缺省优先级比较高,除非用户自己指定一个优先级,而用户指定的优先级(是正数)永远高于核心缺省指定的优先级(是负数)。
优化性能:分布存放,高性能磁盘存放。
文件夹挂载文件夹:
文件类型:none bind 0 0
挂载光盘:
/dev/sr0 /mnt/cdrom iso9660 defaults 0 0
挂载网络服务:nfs,samba
迁移 home 目录到新分区:
建议 init 1 进入单用户模式,防止别人正在使用文件(要确保别人不访问)
新建 /mnt/home 目录,将新分区(格式化)挂载至该目录
cp -a /home/. /mnt/home/
再将新分区挂载到 /home 目录
4.4 移动介质
挂载意味着使外来的文件系统看起来如同是主目录树的一部分
访问前,介质必须被挂载
摘除时,介质必须被卸载
按照默认设置,非根用户只能挂载某些设备(光盘、DVD、软盘、USB 等)
挂载点通常在 /media 或 /mnt 下
使用光盘:
在图形环境下自动启动挂载 /run/media/<user>/<label> 否则必须手动挂载: mount /dev/cdrom /mnt/cdrom
操作光盘:
eject 弹出光盘 eject -t 弹入光盘
创建 ISO 文件:
# cp /dev/cdrom /root/centos.iso # mkisofs -r -o /root/etc.iso /etc # /将/etc 目录打包成 iso 文件
挂载 ISO 文件(ISO 文件只读)
刻录光盘:
wodim -v -eject centos.iso
挂载 USB 介质
# lsusb # 查看 USB 设备是否识别 # lsmod # 查看正在使用的内核 被内核探测为 SCSI 设备 /dev/sdaX、/dev/sdbX 或类似的设备文件 在图形环境中自动挂载: 图标在[计算机]窗口创建 挂载/run/media/<user>/<label> 手动挂载: # mount /dev/sdb1 /mnt
4.5 常见工具
文件系统空间占用等信息的查看工具:
df [OPTION]… [FILE]… -H 以 10 为单位 -T 文件系统类型 -h human-readable -i inodes instead of blocks -P 以 Posix 兼容的格式输出
查看某目录总体空间占用状态:
du [OPTION]… DIR -h human-readble -s summary -max-depth=# 指定最大目录层级
dd 命令:convert and copy a file(转换并复制文件)
dd if=/PATH/FROM/SRC of=/PATH/TO/DEST bs=# count=# if=file 从所命令文件读取而不是从标准输入 of=file 写到所命令的文件而不是到标准输出 ibs=size 一次读 size 个 byte obs=size 一次写 size 个 byte bs=size block size,指定块大小(即是 ibs 也是 obs) cbs=size 一次转化 size 个 byte skip=blocks 从开头忽略 blocks 个 ibs 大小的块 seek=blocks 从开头忽略 blocks 个 obs 大小的块 count=n 复制 n 个 bs
echo {0..9} | tr -d ' ' > /test/f1.txt echo {a..z} | tr -d ' ' > /test/f2.txt dd if=/test/f1.txt of=/test/f2.txt bs=1 skip=2 seek=3 count=4 cat /test/f2.txt abc2345 # 默认截断之后的数,要想不截断使用 conv echo {a..z} | tr -d ' ' > /test/f2.txt dd if=/test/f1.txt of=/test/f2.txt bs=1 skip=2 seek=3 count=4 conv=notrunc cat /test/f2.txt abc2345hijklmnopqrstuvwxyz conv= conversion[,conversion...] 用指定的参数转换文件 转换参数: ascii 转换 EBCDIC 为 ASCII ebcdic 转换 ASCII 为 EBCDIC Icase 把大写字符转换为小写字符 ucase 把小写字符转换为大写字符 nocreat 不创建输出文件 noerror 出错时不停止 notrunc 不截短输出文件 sync 把每个输入块填充到 ibs 个字节,不足部分用空(NUL)字符补齐 fdatasync 写完成前,物理写入输出文件
使用 dd 命令备份 MBR 分区表:
# 使用 dd 命令备份 MBR 分区表: # dd if=/dev/sda of=/tmp/mbr.bak bs=512 count=1 # 破坏 MBR 中的 bootloader # dd if=/dev/zero of=/dev/sda bs=64 count=1 seek=446 # 备份: # dd if=/dev/sdx of=/dev/sdy # 将本地的/dev/sdx 整盘备份到/dev/sdy # dd if=/dev/sdx of=/path/to/image # 将/dev/sdx 全盘数据备份到指定路径的 image 文件 # dd if=/dev/sdx | gzip > /path/to/image.gz # 备份/dev/sdx 全盘数据,并利用 gzip 压缩,保存到指定路径 # 恢复: # dd if=/path/to/image of=/dev/sdx # 将备份文件恢复到指定盘 # gzip -dc /path/to/image.gz | dd of=/dev/sdx # 将压缩的备份文件恢复到指定盘 # 拷贝内存资料到硬盘 # dd if= /dev/mem of=/root/mem.bin bs= 1024 # 将内存里的数据拷贝到 root 目录下的 mem.bin 文件 # 从光盘拷贝 iso 镜像 dd if= /dev/cdrom of=/root/cd.iso # 拷贝光盘数据到 root 文件夹下,并保存为 cd.iso 文件 # 销毁磁盘数据 dd if=/dev/urandom of=/dev/sda1 利用随机的数据填充硬盘,在某些必要的场合可以用来销毁数据,执行此操作以后,/dev/sda1 将无法挂载,创建和拷贝操作无法执行。