14---磁盘与文件系统管理


2017-04-23 22:06 初稿,有编辑则记录于此
2017-04-26 23:23 改动段落,增加图片
2017-04-27 22:17 更改部分谬误之处
-----------------------------------------------------------
本文介绍了从拿到一个磁盘到挂载使用的整个过程,包括基础概念的解释和常用工具的使用方法。
基本概念梳理  G--->T--->P-->E-->Z-->Y-->D-->N
两种磁盘分区方式:MBR(msdos)&GPT
1. MBR(Master Boot Loader)
先说下CHS,这是定位扇区的一种方式,即Cylinder(柱面),Head(磁头),Sector(扇区),柱面的粒度最大,扇区的粒度最小。磁盘上的 0 号柱面,0号磁头,1号分区就是我们说说的 MBR,其大小为 512 Byte。
512B=446B(Boot Loader)+16*4(主/扩展分区信息)+2B(Magic Number,值为 0x55aa 则表明分区表有效,非该值则认为该磁盘无分区)
主分区+扩展分区最多4个,其中扩展分区最多1个,主分区最多4个(此时无扩展分区)。扩展分区再分逻辑分区,我们使用的是逻辑分区。
我们拿上图中的 16 Byte 的分区信息来看下,CHS只有 3 Byte (24 bit,C、H、S各占几位见文末图),可寻址的扇区范围最大为 2 的 24 次方(16777216)个,每个扇区 512 Byte 算的话,磁盘总大小也才 16777216 * 512 = 8589934592 Byte = 8G,这明显与我们的认知相矛盾,因为现在分区动辄就大于8G,更何况磁盘呢。所以当分区大于8G的时候就应该使用 LBA(Logical Block Addressing) 编号来定位一个分区的扇区范围了,即上图中的最后两个字段。但是即便如此,MBR 方式的分区,其磁盘总大小也不过 2 的 32 次方个扇区,换算成字节为 2 TB。当一个磁盘的容量大于 2 TB 的时候,就需要使用 GTP 方式分区了。
2. GPT(GUID Partition Table)分区不再分类(主、扩展、逻辑),linux上支持多达 128 个分区(其实可大于128)
GPT的分区表头部有个MBR,称之为 protective MBR,避免不识别GTP的系统对其再分区(误操作)。
GPT的分区有分区层面的 LABEL 和 UUID     <--- 这两个数据存储在分区表项中
PART LABEL: 其实就是 partition's name,该分区根据根据 type code 被分配一个UUID (这个 UUID 和 type code 是有协议规定的,一一对应,非随机生成)
PART UUID:  分区层面的一个UUID


下文中的 PARTITION 暂时认为是广义上的分区,即文件系统,其可以用如下3中方式标示:
1. 设备文件名
2. 文件系统层面的LABLE
3. 文件系统层面的UUID
===============================
分区--->格式化文件系统--->挂载
VMware上添加 SCSI 硬盘后,fdisk -l 未发现之,可 echo '- - -' > /sys/class/scsi_host/host0/scan 重新扫描下SCSI总线(-之间有空格)
之前的分区是按柱面为单位分的,现在可以不以柱面边界为界限分区。
============
MBR分区
fdisk [OPTION] DEVICE 
磁盘分区工具(菜单化的子命令),device为设备(sda,sdb等)而非分区(sda1,sda2) <--- 默认mbr分区,对GPT支持不好
  -l  list,列出已知的分区表,不指明device,显示全部
fdisk /dev/sda
----------------支持的子命令如下----------------
  u    调节显示单位(sector / cylinder),当使用 p 时 
  p    显示当前硬件分区(包括没保存的修改)
  n    创建新分区
  d    删除一个分区
  t     修改分区的system id(82为swap,83位linux)-----> 分区完成后这些信息写到分区表16B中的一个Byte中,做 LV 和 软RAID 实验的时候建议在相应分区写入正确 type
  w    保存退出
  q    退出(不保存)
fdisk分区完(分区表修改完并w)后,通过以下方式验证:
0.  fdisk -l /dev/sd#
1.  cat /proc/partitions 
2.  lsblk
3.  ls /dev/sd#*
其中0是直接去磁盘读分区信息,1-3是读os在内存中记录的分区信息,若后者没有及时同步,可以使用 partprobe 命令通知os分区表已改变。
partprobe ---> inform the OS of partition table changes
partprobe -s  ---> Show a summary of devices and their partitions.
但 partprobe 在CentOS6 上有bug,所以可用 partx 代替:
新增分区   partx -a  /dev/DEVICE
删除分区  partx -d -n M /dev/DEVICE
show分区信息  partx -s /dev/DEVICE     什么既然是内核写入分区信息到磁盘,那为何还需要partprobe等工具?同步问题出在哪里?
GPT分区
gdisk -l DEVICE  <--- 必须指明device
-------------支持的子命令如下-------------
  p    显示当前硬件分区(包括没保存的修改)
  i     显示详细信息
  c    更改分区名(亦即分区层面的label)
  n    创建新分区
  d    删除一个分区
  t     修改分区的system id(82为swap,83位linux)
   w    保存退出
  q    退出(不保存)
  b    backup 分区表
====================================
parted  <--- 支持以 msdos 和 GPT 方式分区
parted /dev/sdb mklabel msdos|gpt   <--- 根据选择创建分区表,所谓的 partition label 其实就是根据分区表信息判断出来的
parted /dev/sdb print
parted /dev/sdb mkpart {primary|extended|logical} start_size end_size (default by MB)  <--- for msdos
parted /dev/sdb mkpart partition_name  start_size end_size   <--- for gpt,只有gpt才有partition name一说

VFS:Virtual File System 也是内核模块之一
Intel CPU 4种模式:
ring0(内核),ring1(未使用),ring2(未使用),ring3(用户进程)
用户模式(用户空间) 
内核模式(内核空间)

==============
格式化文件系统
sector:硬件物理上存储数据的最小单位
block:系统逻辑上存储数据的最小单位
常见文件系统:
FAT32,NTFS
ISO9660
FFS,UFS
CIFS,ext2,JFS32
ext2,ext3,ext4,xfs,reiserfs,jfs
网络文件系统:nfs,cifs,
集群文件系统:ocfs2,gfs2
linux支持的文件系统在 /lib/modules/`uname -r`/kernel/fs 下,各文件系统自有目录,里面含 .ko 文件
cat /proc/filesystems 显示的系统已经加载的文件系统类型
--------------制作---------------
mkfs( make file system ) 高级格式化
mkfs [option] partition
-t TYPE PARTITIONS
    TYPE={cramfs | ext2 | ext3 | ext4 | ext4dev | msdos | vfat(FAT32).......} 
mkfs执行过程中根据情况调用 mkfs.ext2mkfs.ext3mkfs.ext4等程序,即 mkfs -t ext2 == mkfs.ext2
mke2fs(专门管理ext系列文件)
默认参数在配置文件 /etc/mke2fs.conf 中预置
  -t    格指定文件系统类型,可取{ ext2 | ext3 | ext4 }
  -j    格式化过程中是否在分区中添加日志信息(添加就是ext3,不添加就是ext2)
  -b     BLOCK_SIZE,默认4096Byte,可取值为{ 1024 | 2048 | 4096 }
  -L     LABEL,指定文件系统层面的label,亦即卷标(volume name)   ---->文件系统的 LABEL 存放在超级块中,label的数据长度在哪里控制?
  -U     UUID,指定文件系统层面的uuid          ---->文件系统的 UUID 存放在超级块中
  -m #     maintenance,指定预留给超级用户的块数百分比(#%),mke2fs -m 3 /dev/sda6 即预留3%
  -i #    bytes-per-inode,平均给多少个字节分配一个inode(ext3是4个block,即4*4K Byte,分1个inode)
   -I #    指定 i-node 的大小  
  -N #  指定创建iNode的个数
  -O    Create  a  filesystem with the given features   <--- 哪些选项?待研究!
注意:
逻辑分区设备文件名不稳定(总是从5开始的整齐番号,即使该设备添加删除分区,也保持名称在数值上的连续性)
所以指定设备建议使用LABEL 或 UUID ( 文件系统层面的 LABEL 和 UUID )
findfs 可以找到指定 UUID 或 LABEL 对应的设备文件名
findfs LABEL=your_label
findfs UUID=your_uuid
引申:
inode编号的‘作用域’是在本文件系统内,这也就解释了为什么硬链接不能跨文件系统创建。
-----------查询----------
blkid(查看块设备的属性
blkid [partition]
若分区为 MBR 则显示文件系统层面的 LABELUUID,以及 文件系统类型
若分区类型为 GPT,会增加显示 PART LABEL(亦即分区类型)PART UUID
UUID是随机生成的一串数字,用来唯一标示一个分区,空间够大,不易碰撞,uuidgen 产生uuid
lsblk
blkid [option] [device/partition]
-f    output info about filesystem;filesystem type,LABLE 和 UUID 等
-n    结果不显示表头
dumpe2fs(dump ext filesystem information)
dumpe2fs PARTITIONS
-h    只显示超级块信息
df(已挂载的磁盘使用情况 )
无选项    block的使用情况
     -h   human,磁盘空间的使用情况
     -i   iNode的使用情况
     -T  显示文件系统类型
du 
du [option] [FILE]  <--- 主要用来看目录大小(递归计算)
不加 FILE 显示当前目录下的信息(directory only,但总大小含各目录下文件尺寸,即对目录递归计算)
    -s     summary,不列出含的各文件大小
    -h     human
    -a    列出所有文件大小,对目录递归
-----------------调整------------------
e2label( 用于查看或者定义文件系统的卷标  )
e2label PARTITION NEW_LABEL
tune2fs  调整文件系统的相关属性
tune2fs [OPTION] PARTITION
  -j    不损害原有数据,将ext2升级为ext3
  -m #  调整预留给超级用户的块数百分比(#%)
  -L    用于设定或修改卷标(文件系统层面的 label),与 e2label 功能一样
   -U   指定或修改文件系统层面的uuid  
  -l    显示超级块中的信息,与 dumpe2fs -h partition 类似,但缺少一点点信息 (journal 相关的)
  -r #  指定预留块数
  -c #  指定挂载次数达到#次之后进行自检,0表示关闭此功能
  -i #  指定多少天后进行filesystem自检,0表示关闭此功能
  -O   文件系统属性启用或禁用, –O ^has_journal     <---  待研究
  -o    调整文件系统的默认挂载选项,–o ^acl   <---  信息写在超级块中,具体使用待研究
---------修复---------
fsck(检查修复文件系统
fsck [option] partition
-t FSTYPE  指定文件系统的格式
-a  不询问,自动完成修复
和 mkfs 类似,也是调用 fsck.xfs、fsck.ext2、fsck.ext3 等程序完成检查修复。
e2fsck(专用于修复ext文件系统)   
  -f    强制检查
  -y    回答yes
--------------------
EXT2文件系统结构
超级块是对整个分区的表述,在Block Group1之后的存在(分散在某些Block Group中)都认为是一种备份。
BG描述,仅对所在Block Group的信息。

inode table中每个条目的数据结构是什么样的?
该分区中有多少Block Group?每个Block Group中有多少block?多少inode?这些是否可以人为指定? --->  貌似不可以,待确认。
==================
挂载 & 卸载
mount
1. 挂载点目录事先存在
2. 挂在后目录中的原有文件将会暂时隐藏(最好使用空目录做挂载点)
默认情况下,mount 命令每挂载一个设备,都会把挂载的设备信息保存至 /etc/mtab 文件。
mount [OPTIONS] [-o extra-OPTIONS] PARTITION MNT_POINT(不加参数,则显示当前系统下所有挂载的设备信息,-l 可显示 label 信息)
-t FSTYPE    指定设备的文件系统类型。不使用此选项时,mount会调用 blkid 命令获取对应的文件系统的类型。
                   ext3 可以 挂为 ext2 (导致日志功能不可用),但 ext2 不能挂为 ext3。ext4 和 ext2,3差别较大。
-r    只读挂载
-w   读写挂载(默认)
-n    使用-n选项意味着挂载设备时,不把信息写入/etc/mtab,用 mount 看不到完整挂载信息,可用 cat /proc/mounts  
-a    读入 /etc/fstab 配置文件,挂载该文件中定义的所有(尚未挂载的且挂载选项为 auto )文件系统
-L    用 label 指定要挂载的 PARTITION
-U   用 uuid 指定要挂载的 PARTITION
-B   目录挂目录,如 mount -B /boot /tmp, 此时在 /tmp 下可以看到 /boot 的内容。 --bind 是其长选项
-o  指定额外的挂载选项,也即
    async  sync    设置所有I/O操作为异步模式 | 同步模式
    relatime  noatime    访问文件是否出发 atime 更新(触发条件:1.atime已经太久(超过24小时) 2. mtime 比atime新)
    diratime  nodiratime  访问目录是否出发 atime 更新
    auto  noauto    是否支持自动挂载(若写到 /etc/fstab 则控制是否开机挂载,同时控制 mount -a 时新增条目是否被挂载)  
    exec | noexec   允许可执行文件执行 | 不允许可执行文件执行
    dev | nodev    是否使能文件系统上的设备文件
    suid | nosuid    是否使能文件系统上二进制执行程序的 suid 权限
    remount  重新挂载当前文件系统到相同挂载点(修改挂载选项时不必先 umount,如: mount -o remount,ro /mnt/point)
Defaults:相当于rw, nosuid, dev, exec, auto, nouser, async


挂载文件到指定挂载点

创建文件并格式化之
mount -o loop /home/dechao/filepartition /mnt/filepoint  <--- 挂载一个文件消耗一个 /dev 下的 loop# 设备,系统从 loop0 开始分配
loop# 设备默认为 0~7 共8个,但是修改 /boot/grub/grub.conf ,在 kernel 所在行加上 max_loop=## 即可修改该设备文件数量。
可以使用 losetup /dev/loop# part_file 来手动关联 loop# 设备和文件,关联后可以挂 loop # 到指定挂载点,不用再写文件名了
通过 losetup -a 查看这种关联关系,通过 losetup -d /dev/loop# 解除这种关系

---------------查询-----------------
findmnt(list mounted filesytems info)
findmnt [option] partition|mnt_point
-n    不显示表头
除此之外df,mount,cat /etc/mtab,cat /proc/mounts等都可以查询挂载信息
---------------卸载-----------------
umount
umount { PARTITION | MNT_POINT }
要求:挂载的设备没有进程使用
当一个设备被其他用户使用的时候,卸载会显示busy,可以使用下列方法查看哪个进程在访问挂载点

lsof(list open file)
lsof mnt_point  <--- 查看哪些进程在访问挂载点,然后手动 kill 进程
fuser(list process use file or socket)
-v     vobose 
-k    杀进程
-m    指定设备文件或挂载点
fuser -mv MNT_POINT    查看正在使用的文件或socket的进程
fuser -km MNT_POINT    终止正在访问此挂载点的所有进程
--------------
开机挂载
/etc/fstab(man 5 fstab)
该文件只能被程序读,不能被程序写,修改该文件内容,需要手动。
操作系统在初始化时,会自动挂载  /etc/fstab 中的每个文件系统(如果挂载选项没有noauto),字段解释如下:
要挂载的设备挂载点文件系统类型挂载选项转储频率(每多少天做一次完全备份)文件系统检测次序(0表示不检查)
转储频率字段与dump相关,可以man dump一下。 <---  如何转储?什么意思?
检测次序字段与开机后检查磁盘(是否clean)的顺序有关,0表示该文件系统不需要做 fsck。如果非0,且开机检查出问题(如使用LABEL挂载的,LABEL变了),则无法正常启动,同时所有文件系统默认为 ro 挂载。此时,remount 下把挂在选项改为 rw ,进入 /etc/fstab 把这个值改为0,然后进入系统处理。
默认挂载选项 defaults:相当于rw, nosuid, dev, exec, auto, nouser, async

如果开机后想目录挂目录,则格式如下:
/dir1  /dir2   none bind 0 0
如果开机后想文件(loop#)挂目录,则格式如下:
/filename  /mnt_point  filesystem_type  loop 0 0 
-------------------------------------------------------------------------------------------------------------
光盘在 CentOS 上为/dev/sr0,但在其他系统上不一定,不过 /dev/cdrom# 是通用的,它是个软连接,链接到真正的光盘设备文件。
自动挂载
autofs
两个配置文件: /etc/auto.master     &     /etc/auto.misc <---默认的,可以在 auto.master 里面指定 
/etc/auto.master中     
/misc   /etc/auto.misc    #格式为   mount-point [map-type[,format]:] map [options],这里的map可以理解为子配置文件
/etc/auto.misc中 
mycd    -fstype=iso9660,ro,nosuid,nodev :/dev/cdrom1   #格式为 key [ -mount-options-separated-by-comma ] location
配置文件设置完成后重启服务 rpm包中的 /usr/sbin/automount 安装后可配置启动为服务

为什么要挂载?例如设计的时候直接用/dev/sdb5不可以吗,/dev/sdd5设计成目录,直接进去就可以访问不好吗?
<--- 如果直接使用,那挂载选项怎么设置?退一步讲,如果可以手动设置,那把哪一个设备挂到 /dev/sdb5? 还是得要一个符号指明某设备。其实linux中/dev/sdb5就是指明这个设备,然后我们再指定挂载到哪个目录进行操作。
==================================================
格式化为交换分区
格式化之前的分区过程(fdisk)中,建议把该分区类型调整为82(Swap),其实就是把分区表中的 type 值设置为此数值。
mkswap PARTITION/DEVICE
  -L    LABEL  设置分区的卷标
--------------
挂载交换分区
swapon [OPTION] /PARTITION/DEVICE
  -a    启用所有定义在 /etc/fstab 文件中的交换设备
  -s    查看当前 swap空间 在 swap 设备上的分布情况,及其优先级(数越大优先级越大,挂在选项中添加 pri=# 指定)

swapon  /dev/sda8
swapoff /dev/sda8

场景:swap分区不够用了,而磁盘上没有多余空间创建新的swap分区了,但空间足够,如何处理?
创建一个镜像文件,将其格式化为swap格式,挂载使用。
dd if=/dev/zero of=/var/swap_file bs=2M count=256  //创建一个512M的文件
mkswap /var/swap_file
swapon /var/swap_file   <---  没有消耗 loop #,不像mount
挂载完成后使用free看看,对比挂载前后swap空间 
==================================================
设备文件
ls -l /dev 执行后在属组之后没有size列,但增加了两列数字,分别为:
     设备主设备号(major number):标示设备类型
     设备次设备号(minor number):标示同一类型的不同设备  

mknod 创建设备文件
mknod [OPTION]... NAME TYPE [MAJOR MINOR]
    -m  mode, 设备文件的mode
ls -l /dev/sdb    <--- 记下主次设备号8,16
rm /dev/sdb
mknod /dev/sdhehe b 8 16   <--- 相当于做一个硬链接  tty2硬链接到/tmp/hehe, echo "aa" > /tmp/hehe时,tty2可收到消息。
echo "hello" >> /dev/pts/1
echo "hi,boss" >> /dev/tty2
echo "bye" >> /dev/sda1  非常危险,会直接写入硬盘分区,破坏原始数据
特殊设备:
/dev/zero
/dev/null

dd(convert and copy a file
dd if=src_file of=dst_file bs=block_size count=amount_block skip=# seek=##    <--- 默认以 Byte 为单位
<--- skip表示从if跳过多少bs后开始读,seek表示从of跳过多少bs后开始写,如果 of 已经存在,则可定点修改部分文件内容
备份MBR
  dd if=/dev/sda of=/mnt/usb/mbr.bak bs=512B count=1
制作系统
  dd if=/home/dechao/os7.iso of=/mnt/sdb bs=2M
free
  -m  以M为单位显示

知识点补充:
cat /dev/cdrom > /home/dechao/rhel6.iso  制作光盘镜像
dd if=/dev/zero of=/var/test bs=1M count=1024  /dev/zero被称为泡泡设备,可以往外吐0。这条命令会创建一个全0的大小为1G的文件。
dd if=/dev/zero of=/var/test.fake seek=1023 bs=1M count=1  把输入文件的前1023个block跳过,仅将第1024个block写入目标文件。使用ls和du分别查看其大小,结果不一样。

x86  虚拟地址的概念,注意不是虚拟内存。
粗略理解:以32bit CPU为例,进程认为自己占用全部4G进程,而内核会把这个虚拟地址空间最终转化为物理内存空间。
当物理内存空间不够的时候,在硬盘上会找一个存储空间,模拟成内存,称之为交换空间。
page out:数据从内存转储到磁盘
page in:数据从磁盘转储到内存


MBR 分区细节延伸
曾经磁盘,8G的容量是上限,由于内外磁道sector数一样,后来出现了ZBR(zoned bit record)使外道可以放更多磁盘
fdisk -l /dev/sda中的255heads,假的。固态磁盘也沿用这些参数,但是并没有。分区现在也可以不是整柱面分

CentOS 下测试发现扩展分区可分 56 个逻辑分区,这是由操作系统限制的,应该有一个MAX值, 在哪里呢?

GPT 分区细节延伸
(待补充)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值