这一节内容我们一起来详细了解磁盘的工作原理;
磁盘管理
首先,我们知道计算机的三大组建:CPU、内存、和I/O设备;其中磁盘就是属于外部的I/O设备,用于永久的存储文件数据;相对于CPU和内存而言,当前使用较多的机械磁盘还是处于“上一个阶段”的产品,对比起CPU内存这样的电子产品而言,速度可想而知。
我们常见的外部存储设备有:U盘、光盘、软盘、磁盘、磁带等;其中U盘(闪存)为深圳朗科研发出来的,这些设备都是可以实现数据的永久存储的。
其中,我们着重介绍磁盘的工作原理。
磁盘的物理组成
巨磁电阻效应的发明:
1988年,费尔和格林贝格尔各自独立发现了“巨磁电阻”效应:非常弱小的磁性变化就能导致古大的电阻变化。
当硬盘体积不断变小,容量却不断变大时,势必要求磁盘上每一个被划分出来的独立区域越来越小,这些区域所记录的磁信号也就越来越弱。借助“巨磁电阻”效应,人们才得以制造出更加灵活的数据读出头,是越来越弱的磁信号依然能够被清晰读出,并且转换成清晰的电流变化。
1997年,第一个基于“巨磁电阻”效应的数据读出头问世,并很快引发了硬盘的“大容量、小型化”革命。
1、磁盘的大概结构:磁盘、轴与r/w head磁头中间
用于数据存储的为盘片(platters),盘片都是围绕着主轴(spindle)进行旋转,数据的读取与写入都是通过磁头(read/write head)来完成,而读写横向看来的磁盘结构(actuator arm assembly)如下图:
2、磁盘常见的几个基本概念
扇区(Sector),磁道(Track)、以及柱面(Cylinder);
磁道(Track):在一个盘片上,将其划分成n各同心圆,而这一个同心圆就叫做一个磁道;
扇区(Sector):在一个磁道上,将其划分为多个512bytes大小的磁盘的扇形区域,这每一个扇形区域就叫做一个扇区;
柱面(Cylinder):在多个磁盘上处于同一个地方的扇区的结合,就是柱面;
【数据存储,磁盘分区都是根据柱面来进行分区的】
------------------------
分区(partition):在我们的windows系统上,C盘/D盘,这些概念实际上就是分区,而分区,实际上就是我们在磁盘上建立起一个逻辑边界,这就叫做分区(partition)。
分区是一个动作,分好的区我们需要为其写入文件系统,这个过程我们叫做格式化,只有写入文件系统的分区,才能够进行数据存储。格式化的内容我们在后面再进行介绍;
这里,我们了解一个最为特殊的区域--MBR(master boot record)主引导记录MBR也就是我们磁盘上的第一个分区,它是属于物理概念,它是我们磁盘上处于最外面的一个扇区,大小为512bytes,它的主要作用就是加载主引导程序;
在MBR上,446bytes的大小为BootLoader引导程序【主引导分区对于系统而言至关重要,如果主引导分区故障,系统是无法启动的】;
64byter大小为磁盘标识符,1个磁盘标识符为16bytes,所以Linux最多只能有4个磁盘标识符,而这里所说的是主分区标识符,如果将这四个标识符空间做一个扩展标识,则又能够添加多个逻辑分区,所以这里我们不必担心磁盘的分区不够的问题;
【这里需要记住:1、主分区加扩展分区最多有四个;2、扩展分区最多有一个;3、逻辑分区可以有任意个,前提是先划分一个扩展分区】
最后2bytes是作为魔数,magic number,它用来标记MBR分区是否有效;
-----------------------
这里,我们再介绍下系统的启动过程:
在系统启动的时候,内存为空,而CPU读取数据只能从内存中读取,此时,我们的电脑会将BIOS芯片中的一段启动程序自动加载到内存中来,完成如下两个工作:1、硬件设备的自检;2、自检无误,查找可以启动的系统。一般就是按照BIOS设置的查找顺序来查找系统,如果读取到的硬盘的系统文件,就会首先加载MBR分区中的BootLoader代码。通过读取BootLoader指定对应的分区信息,以及分区内容,找到操作系统加载到内存中来。内存再加载系统内核文件,内核文件关联具体程序,一步一步将所有需要的程序启动起来;
【BIOS-->1、自检;2、加载BootLoader-->读取分区,加载系统内核-->系统内核启动应用程序】
这就是我们系统启动的过程;
3、磁盘的读写延迟从屋里角度来说
磁盘分区是根据柱面来实现分区的。一般柱面越是靠外,则读取速度就越快。读取数据的时候,我们需要等待磁头到达对应的柱面,如果数据转过去了,就得等待数据再次转回来,而这个寻道时间,就是我们的延迟时间;
所以,如果盘片的转速越快,则延迟越小,这样的话读取数据的速度就越快;一般电脑磁盘的转速为5400rpm(转/分)或则是7200rpm,因为磁盘旋转速度太快,所以磁盘都要求在无尘的环境下进行工作;
文件系统
对磁盘做了分区以后,如何来进行数据存储呢?我们说,如果不对磁盘进行分区格式化,则这个分区是无法存储数据的,而格式化是做了什么操作呢?
格式化就是对分区做了文件系统的安装!!!
分好的区,就好像一个图书馆,如果没有人管理,直接就把一大堆的书任意放置在图书馆里,则当用户需要查找某一本书的时候,将会是一个非常困难的事,而文件系统,就是管理数据的一个系统;就类似于图书馆对于图书管理的整个系统体系!
文件系统:简单的来说,它就是一种软件,它并不是直接存储在这个分区上,我们可以将其理解为一个分区的管理软件,专门用来做数据管理;
文件系统结构
文件系统是如何来管理数据的呢?我们先看下图:
我们将分区分为两个部分,数据存储区和元数据存储区,数据存储区主要用来进行存储,而元数据存储区,则是用来存储数据的元数据,例如数据大小、数据类型、数据存储的时间等等!
元数据存储区:
1、iNode信息(index node):通过 ls -i 我们可以查看到数据的iNode号,而这些iNode号,就与数据存储区的块信息对应,我们通过iNode信息来查找真实的数据所存储的位置,它就类似于书本的目录,包含了书本的所有类容;【同时,iNode信息也存放了数据的元信息,例如权限、属主与属组、时间戳等等信息,就是没有文件名】
2、iNode位图(bitmap):iNode信息是有限的,我们如何知道哪些iNode信息没有被使用,哪些iNode的信息已经使用了呢?如果通过遍历元数据存储区来查找则会非常麻烦,所有我们就有了iNode位图,只需要通过iNode位图来判断iNode信息的使用情况;
3、块位图(block bitmap):同理,如果想查找哪些块没有被使用,则不需要去遍历整个数据存储区,而是只需要查看块位图即可;
数据存储区:
在数据存储区中,我们会将空间大小分配为大小相等的块(block),而块的大小为2^n,一般为4096,可以自己调整为1024或者2048或者更大;
数据块一般用来存储普通数据,普通的文本文件“-”,使用数据块较多,另外一类则是目录文件“d”,使用数据块较多;“p”管道文件,“s”套接字文件,以及“d”“c”设备文件都不占用块的大小;目录文件的块的数据则存放的为,iNode信息和对应iNode信息的目录名或者文件名;
文件查找、新建、删除、复制与移动
*查找:例如查找 /etc/log/message 的过程
首先,根是自引用的;此时,我们从根开始查找,找到 / 所对应的块,这时候,在这个块下面存放的是 / 下的所有文件目录的名称以及iNode信息,此时就会看到 log 目录的 iNode 信息;第二步,通过查找 log 目录的iNode信息找到 log 对应的块,这个里面存放了 log 目录下对应的文件目录的名称和iNode信息,包括 message 文件;第三步,通过message 文件的iNode信息找到message文件对应的块,这时候就能找到message文件对应的数据了;
最后,在查找到数据以后,我们会将目录信息进行缓存,保存一份,再下次查找该文件的时候就可以直接查找缓存信息;
新建:新建文件,则会查看iNode位图与块位图,0表示该iNode位图或者块没有被占用,可以用来新建文件;
删除:同理,在删除文件的时候,则是将iNode位图和块位图对应的位置置位为0,则表示对应的块和iNode条目没有被使用;【所以,数据在磁盘存储的时候是没有被清除的,通过数据恢复工具是可以将数据恢复的;】
复制:在同一个分区下,不同的目录上的数据复制,会很快,因为这里我们只是将对应的iNode数据指向修改了,如果是不同的分区之间的数据复制,则会很慢,因为它将整个块中的数据都要进行复制;
移动:移动的原理和复制相同;
常见的文件系统类型
可以说,Linux几乎支持所有的文件系统类型;我们要知道,文件系统功能是属于内核功能,我们通过mkfs应用进程,将内核对应的文件系统功能写入到磁盘中,这就是格式化的过程;
格式化分为两种:1、低级格式化,这一般是在磁盘出厂的时候由厂家来为我们完成, 它是用来创建磁道的;2、高级格式化,例如 mkfs -t ext3 /dev/sda3 ,这就是我们常见的格式化操作,用来为 /dev/sda3 这个磁盘分区写入文件系统;
常见的文件系统:
windows系统下常见的文件系统为fat32、NTFS、cifs(网络文件系统、网上邻居使用的);
Linux下常见的文件系统ext2、ext3、ext4、xfs、reiserfs、jfs(IBM)、vfat(windows系统的fat32)、NTFS;集群文件系统ocfs2;网络文件系统nfs;全局文件系统gfs2;
既然有这么多文件系统,那么每一个文件系统对于存储上它上面的文件的操作是不尽相同的,这样的话,对于开发人员而言,就需要为每一种文件系统开发一套文件的处理方式,这是很不合理的!
为了避免这种情况,我们通过VFS,虚拟文件系统作为接口,来处理数据这样就避免了为每个文件系统开发不同的处理方式了;【虚拟文件系统VFS功能也是属于内核功能!】
链接文件与设备文件
在我们了解了文件系统以后,我们着重了解两类文件--链接文件和设备文件;
链接文件--l:链接文件分为两类,软链接与硬链接;
软链接:也叫做符号链接;这个类似于windows系统下的快捷方式,软链接的iNode详细指向其他文件的iNode信息,而不是指向数据存储区的块信息;
ln -s 参数为新建软连接,而 -v 参数表示显示创建链接的详细信息;
我们可以看到文件b.txt是以“l”开头,同时在原本为文件大小的地方,存放的是 a.txt 文件的字符长度;
如果删除原文件 a.txt 则 b.txt 的连接文件也会失效,但是如果从新有新建一个 a.txt 而这个 a.txt 已经不是原来的文件了(iNode号不同),则这个 b.txt链接文件是依然有效的;
【总结:1、软链接可应用于目录;2、可以跨越文件系统;3、不会增加文件被链接的次数;4、其大小为指定的路径所包含的字符个数;】
硬链接:硬链接是将多个文件指向同一个block。只有在删除所有的链接文件后,这个文件才会被删除;
ln 不加 -s 即是创建硬链接文件;
我们可以看到在在权限后面有一个“2”,这里就表示文件的连接数,只有删除所有链接文件才会被删除;
硬链接的iNode信息是相同的,说明他们指向的就是同一个文件;
【总结:1、硬链接只能对文件创建,不能应用与目录;2、不能夸文件系统创建;3、创建硬链接会增加你文件链接数】
设备文件--b,c:b 表示块设备文件,是按照块为单位,随机访问的设备,例如硬盘;c 表示字符设备文件,是按照字符为单位,是线性设备,例如键盘;
/dev 主要就是用来存放设备文件的目录;
设备文件主要包含两个内容,主设备号(major number)和次设备号(minor number),主设备号用来表示设备类型,此设备号用来区分同种类型设备的不同设备;
我们可以通过mknod来创建设备文件,例如:
mknod [option] ... NAME TYPE [MAIOR MINOR]
-m MODE #指定设备权限 -m 640 就是指定设备权限为 rw-r-----
*这里我们有一个小技巧:可以通过重定向,将输入内容传递到其他终端,如下图:
w 命令查看有哪些终端连接在该系统上,在通过 >> 将对应的信息在别的 pts 终端上面输出;
磁盘管理操作
硬盘设备的命名
硬盘设备的设备名,首先判断是什么类型的磁盘:IDE、ATA的磁盘为 hd;SATA、SCSI、USB的磁盘为sd;
如果有多块磁盘,则用 a、b、c ... 来进行区分;
若果是同一块磁盘上的多个分区,则用 1、2、3 ... 来进行区分;
例如:sda 为第一个磁盘,sdb 则为第二个磁盘,sda1, 为第一个磁盘的第一个分区,sdb2 则为第二个磁盘的第二个分区;
【逻辑分区可以有多个,扩展分区只能有一个,主分区最多有四个】
磁盘分区--fdisk
fdisk命令用来对磁盘进行分区操作;
-l 查看分区情况
分区格式化(写入文件系统)--mkfs,mke2fs
mkfs make file system创建文件系统
/proc/partitions #查看系统所支持的文件系统;其中大部分为伪文件系统;
-t FSTYPE 指定所需要创建文件系统的类型
例如:mkfs -t ext2 /dev/sdb1
这里我们要注意, -t 参数可以有对应的命令来替代;
例如:mkfs -t ext2 = mkfs.ext2; mkfs -t ext3 = mkfs.ext3
mke2fs make ext2 file system创建ext类型的文件系统
-j 则是指定创建ext3的文件系统,不指定默认的ext2文件系统
例如:mke2fs -j /dev/sdb2
-b 指定块大小,默认为4096,块大小只能为2^n;
-L 指定卷标
-m NUMBER 指定给root用户预留的磁盘空间百分比,默认为5%
-i BYTE 用户指定为多少字节空间创建一个iNode,默认为8192;这里给出的这个数值应该为块大小的2^n倍;
例如:mke2fs -i 4096
-N NUMBER 指定创建iNode的个数;
-F 强制创建文件系统,一般如果问价系统已经被挂载,则无法写入文件系统,使用 -F 则表示强制创建文件系统,不管分区是否被挂载;
-E 用户指定额外文件系统属性;
【这里提到的所有的参数,在mkfs命令下都能运行;】
blkid 查询或者查看磁盘设备的相关属性
例如:blkid /dev/sdb1 #查看/dev/sdb1的uuid、卷标、文件系统类型等基本信息
e2label 为分区添加卷标
e2label 设备文件 卷标
例如:e2label /dev/sdb1 Test-lvm
tune2fs 调整文件系统的相关属性
-j 将ext2文件系统转换为ext3类型的文件系统,ext2可以转ext3 但不可以转回,转回数据丢失;
例如:tune2fs -j ext3 /dev/sdb1 #将原本的文件系统类型调整为ext3
-L 为分区设定卷标;
-m 调整root用户预留的空间百分比,用法与mke2fs相同;
-r 指定root用户的预留空间的块数,不能和 -m 一起使用;
-o 设定默认的挂载选项;
acl 指定文件系统的acl功能,有点类似于setfacl文件的过滤功能;
-c 指定挂载次数达到多少次后进行自检,0或者-1表示关闭此功能;
-i 指定每隔多少天后进行自检,0或者-1表示关闭此功能;
-l 显示超级块中的信息
例如:tun2efs -l /dev/sdb1
dumpe2fs 显示文件属性
例如:dumpe2fs /dev/sdb1 #这里显示了分区从哪个组到哪组,起始块是多少,结束块是多少,那些块里面是有备份的那些没有;
-h 和tune2fs一样,也是显示超级块信息的
fsck 检测并修复文件系统
-t fstype 指定文件系统类型,也可以不指定,fsck能够自动识别文件系统,但是一定不能指错了;
-a 进行文件系统的自动修复;
e2fsck 专门用来检查并修复ext2和ext3的命令
-a 自动修复,不用询问
-f 强制检查
例如:e2fsck -f /dev/sdb1
-p 也是自动修复,-a 是为了兼容fsck命令
磁盘分区挂载与卸载--mount,umount
挂载:将新的文件系统关联至当前根文件系统;这个动作就是为磁盘分区找一个接入入口,有了这个访问的入口后,就能够访问到这个分区上的所有文件内容;
卸载:将某文件系统与当前文件系统的关联关系移除掉;
mount 挂载
用法:mount 设备名 挂载点
设备名:可以是设备文件名,也可以是卷标(LABEL=""),也可以是UUID(UUID="");
挂载点:也就是一个目录
【但是,这个目录最好是一个空目录,同时,这个目录没有被任何进程调用,如果这个目录里面存在其他文件,当挂载设备后,这些原有的文件就会别隐藏;】
例如:mount /dev/sdb1 /mnt/test #这样,你在/mnt/test目录下编辑的所有文件,都保存于/dev/sdb1这个分区下,默认情况下会有一个lost+found目录;
mount 直接回车,不带任何参数,就是查看系统的挂载情况;
参数以及用法:mount [option] [-o option] device mount_point
-a 直接指定挂载 /dev/fstab 目录下的所有文件,这里是我们做开机自动挂载的默认目录;
-n 默认情况下,mount命令没挂载一个设备,都会把挂载的设备信息保存至 /etc/mtab 文件下;使用 -n选项,就是说挂载设备后,不把信息写入到 /etc/mtab 这个文件里面来;
-t fstype 指定正在挂载的设备上的文件系统的类型,不适用此选项,则mount命令能够自动识别;
-r 只读挂载,一般在挂载磁盘的时候会使用到;
-w 读写挂载,默认情况下,磁盘挂载的时候就是读写挂载;
-o 指定额外的挂载选项,也可指定问价那系统启用的属性;
async 异步写入(默认就是异步)
atime 指定时间戳
auto 自动挂载,can be mounted with the -a option
default 使用默认参数挂载
dev 指定固定设备文件
exec 容许挂载二进制的文件
_netdev 映射文件系统
owner 容许普通用户挂载这个磁盘
remount 从星挂载当前文件系统
例如:mount -o remount,ro /dev/sdb1 #重新挂载/dev/sdb1同时指定为只读权限;
ro 只读挂载
rw 读写挂载
sync 同步挂载
suid 挂载的时候提供suid权限
umount 卸载文件系统
用法:umount 设备名 或者 umount 挂载点
卸载要注意:挂载的设备没有被进程使用;
swap分区--mkswap,swapon/swapoff与dd
swap是系统的交换分区,是用来弥补内存不足的时候,占时顶替内存的分区空间;
free 查看系统内存的使用情况
fdisk /dev/sdb2 #先创建一个交换分区
注意,这里我们一定要将 /dev/sdb2 分区的分区类型修改为 82 Linux swap分区才行;
mkswap /dev/sdb2 #创建swap磁盘分区
-L LABEL 可以添加卷标
swapon /dev/sdb2 启用这个磁盘分区,同理 swapoff /dev/sdb2 就是关闭这个磁盘分区,注意:交换分区是不用挂载的;
本地虚拟回环设备:
如果我们内存不够,可以通过将磁盘的空间划分为swap分区来临时解决,如果磁盘空间也不够了,又不能添加新的磁盘,这时候我们该如何解决这个问题呢?
我们可以创建一个镜像文件,比如:模拟一个100G的空间,这100G的空间就可以用来进行数据存储,但是这100G的空间实际上只占有1m甚至更小的物理空间;
dd convert and copy a file 装换或者复制一个文件
例如:dd if=/etc/inittab of=/root/inittab 将文件/etc/inittab复制到/root/inittab
这里我们需要注意一下dd与copy的区别,他们都是用来对文件进行复制的,但是,dd是直接对磁盘上的内容进行操作,所以,它可以复制一个文件的部分内容;而copy则是将要复制的文件移动到内存中,再由cpu进行复制操作后,放回到对应的磁盘位置中;所以,dd的效率要高很多;
if=源数据 #input file
of=目标数据 #output file
bs=数值 #一次复制多大的单位
count=数值 #将复制的文件转换为多少个字节来进行存储
例如:dd if=/dev/sdb of=/mnt/usb/mbr.backup bs=512 count=1
dd if=/mnt/usb/mbr.backup of=/dev/sdb bs=512 count=1
#这就是使用dd命令来做磁盘备份,备份MBR分区,又可以通过dd命令将MBR分区还原;
dd if=/dev/zero of=/var/swapfile bs=1M count=1024
#/dev/zero 文件叫做泡泡文件,可以凭空创建磁盘空间【/dev/null 黑洞设备,只要指向这个文件的内容都会被删除】