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.ext2,
mkfs.ext3,
mkfs.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 则显示文件系统层面的
LABEL 和
UUID,以及
文件系统类型
若分区类型为 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 分区细节延伸
(待补充)