![5e33f433a6628fbd236d45a2ae3b91bc.png](https://i-blog.csdnimg.cn/blog_migrate/db5a91960dd7b069586fd094ee643aa2.png)
何为分区?
分区是将磁盘按柱面进行物理上的划分,划分好分区后还要进行格式化,然后再挂载才能使用。而格式化分区的过程其实就是创建文件系统。
分区好处
- 隔离系统和程序
- 优化I/O性能
- 提高修复速度
文件系统种类
CentOS 5和CentOS 6上默认使用的ext2/ext3/ext4;
CentOS 7上默认使用的xfs;
windows上的NTFS;
光盘类的文件系统ISO9660;
MAC上的混合文件系统HFS;
网络文件系统NFS;
Oracle研发的btrfs;
还有老式的FAT/FAT32
文件系统组成
硬盘的读写IO一次是一个扇区512字节,如果要读写大量文件,以扇区为单位肯定很慢很消耗性能,所以Linux中通过文件系统控制使用"块"为读写单元。
block
块的大小一般为1K/2K/4K;
读一个或多个块时,文件系统的IO管理器通知磁盘控制器要读取哪些块的数据,硬盘控制器将这些块按扇区读取出来,再通过硬盘控制器将这些扇区数据重组返回给计算机;
使用block的好处是读写性能大大提高,但是可能造成空间浪费
Inode
把数据直接存在集合里,如果没有索引,查找文件是非常耗时困难的;文件系统存储数据也一样,可以通过扫描索引找到对应的数据来优化存储方式。
文件系统上索引技术具体化为索引节点(index node),在inode中存储了inode号、文件类型、权限、文件所有者、大小、时间戳等元数据信息,最重要的是存储了指向属于该文件block指针。
inode大小一般为128字节或256字节
block和inode大小最好是根据业务类型调节,因为涉及到磁盘的空间浪费和读取性能,设置block和inode大小可以在格式化指定:
mkfs.ext4 -b 4096 -I 1024 /dev/sdb1
Inode深入了解
它的默认值由/etc/mke2fs.conf文件中指定,inode_ratio表示每多少个字节就分配一个inode号。
一个inode中最多只能有15个指针,前12个指针i_block[0]到i_block[11]是直接寻址指针,第13个指针i_block[12]是一级间接寻址指针;第14个指针i_block[13]是二级间接寻址指针;第15个指针i_block[14]是三级间接寻址指针;这样一个innode就不会限制文件最大上限
预留的innode号
- Ext4的特殊inode
- Inode号 用途
- 0 不存在0号inode
- 1 虚拟文件系统,如/proc和/sys
- 2 根目录
- 3 ACL索引
- 4 ACL数据
- 5 Boot loader
- 6 未删除的目录
- 7 预留的块组描述符inode
- 8 日志inode
- 11 第一个非预留的inode,通常是lost+found目录
bmap
往磁盘写数据时,如何快速的知道哪个block是空闲的呢?
位图使用0和1标识对应block是空闲还是被占用,0和1在位图中的位置和block的位置一一对应,第一位标识第一个块,第二个位标识第二个块,依次下去直到标记完所有的block。
例如:在位图中1个字节8个位,可以标识8个block。对于一个block大小为1KB、容量为1G的文件系统而言,block数量有1024*1024个,所以在位图中使用1024*1024个位共1024*1024/8=131072字节=128K,即1G的文件只需要128个block做位图就能完成一一对应。通过扫描这100多个block就能知道哪些block是空闲的,速度提高了非常多。
bmap的优化针对的是写优化,读速度基本是受硬盘本身性能的影响而与文件系统无关(为什么)
Inode-table
多个inode合并存储在block中,将这些物理上存储inode的block组合起来,在逻辑上形成一张inode表,
解决空间浪费,避免每个仅128字节的inode都要单独占用一个block
imap
如何知道某一个inode号是否已经被分配了呢?
位图使用0和1标识inode号是否被分配,0和1在位图中的位置和block的位置一一对应,称为inodemap简称为imap
但是随着文件系统空间越来越大,例如文件系统是100G时,100G的文件系统要使用128*100=12800个1KB大小的block存储bmap,所以需要将文件系统占用的block划分成块组,每个块组有自己的imap范围、inode table范围、bmap范围等
块组
块组在文件系统创建完成后就已经划分完成了,那一个块组包含多少个block?多少个inode呢?
文件系统根据每个block的大小以及bmap至多只能占用一个完整的block的标准计算块组个数
例如现在block的大小是1KB,一个bmap完整占用一个block能标识1024*8= 8192个block,每个块组是8192K即8M,创建1G的文件系统需要划分1024/8=128个块组;
文件系统结构
![69d674c1725ddc9957fd0894e51d4561.png](https://i-blog.csdnimg.cn/blog_migrate/fea3d27e0aa9131886977f883d15275f.jpeg)
Boot block
如图,引导块是分区上的第一个块,占1024字节,但是不是所有分区都有这个boot sector(只有装了操作系统的主分区和装了操作系统的逻辑分区才有);
存放的是boot loader,这里的Boot loader和mbr上的boot loader是存在交错关系的
开机启动的时候,首先加载mbr中的bootloader,然后定位到操作系统所在分区的boot serctor上加载此处的boot loader
![c138b2efa1f1df73e12e6f7e2b326694.png](https://i-blog.csdnimg.cn/blog_migrate/dc3f0f5ef012b687a6ddacf58c952a43.jpeg)
不过这种启动方式已经弃用了,现在很多使用grub来管理启动菜单
![c2e08c76ac5a20865771a978cdebd025.png](https://i-blog.csdnimg.cn/blog_migrate/0954f725abb86e26b1c0db03de1aeec6.jpeg)
superblock
文件系统怎么知道分了多少个块组呢?文件系统本身的属性信息如各种时间戳、block总数量和空闲数量、inode总数量和空闲数量、当前文件系统是否正常、什么时候需要自检等等这些信息存储在哪里?
占一个block的超级块来存储;df命令读取的就是每个文件系统的superblock;
超级块丢失或损坏必将导致文件系统的损坏;所以在块组0、1和3、5、7幂次方的块组中保存超级块的备份,当Group0上的superblock损坏或丢失才会找下一个备份超级块复制到Group0中来恢复文件系统
GDT(块组描述符表)
每一个块组信息使用32字节描述,所有块组的块组描述符组成块组描述符表
Reserved GDT
保留GDT用于以后扩容文件系统使用,防止扩容后块组太多,使得块组描述符超出当前存储GDT的blocks。保留GDT和GDT总是同时出现,当然也就和superblock同时出现了。
Data Block
不同的文件类型,数据block中存储的内容是不一样的
- 对于常规文件,文件的数据正常存储在数据块中。
- 对于目录,该目录下的所有文件和一级子目录的目录名存储在数据块中
- 文件名不是存储在其自身的inode中,而是存储在其所在目录的data block中。
- 对于符号链接,如果目标路径名较短则直接保存在inode中以便更快地查找,如果目标路径名较长则分配一个数据块来保存。
- 设备文件、FIFO和socket等特殊文件没有数据块,设备文件的主设备号和次设备号保存在inode中。
目录文件的data block
![6e0dda46f03e9c3f638e2904e40d385e.png](https://i-blog.csdnimg.cn/blog_migrate/27a30155ca081b8a2d06e3a735ea6271.jpeg)
目录文件,其inode记录中存储的是目录的inode号、目录的属性元数据和目录文件的block指针,这里面没有存储目录自身文件名的信息。
目录的data block中并没有直接存储目录中文件的inode号,它存储的是指向inode table中对应文件inode号的指针,暂且称之为inode指针
定位指针是需要x权限的?
硬连接
多个文件的inode相同,也就即inode号、元数据、block位置都相同
创建一个文件的硬链接,实质上是多一个指向该inode记录的inode指针,并且硬链接数加1
删除文件的实质是删除该文件所在目录data block中的对应的inode指针,所以也是减少硬链接次数
不能跨分区创建硬链接,因为不同文件系统的inode号可能会相同,如果允许创建硬链接,复制到另一个分区时inode可能会和此分区已使用的inode号冲突。
软链接
软链接就是字符链接,链接文件默认指的就是字符链接文件
读取文件
例如执行"cat /var/log/messages"
1、找到根文件系统的块组描述符表所在的blocks,读取GDT(已在内存中)找到inode table的block号
因为GDT总是和superblock在同一个块组,而superblock总是在分区的第1024-2047个字节,所以很容易就知道第一个GDT所在的块组以及GDT在这个块组中占用了哪些block。
GDT早已经在内存中了,在系统开机的时候会挂载根文件系统,挂载的时候就已经将所有的GDT放进内存中。
2、在inode table的block中定位到根"/"的inode,找出"/"指向的data block
ext文件系统预留了一些inode号,其中"/"的inode号为2,所以可以根据inode号直接定位根目录文件的data block
3、在"/"的datablock中记录了var目录名和指向var目录文件inode的指针,并找到该inode记录,inode记录中存储了指向var的block指针,所以也就找到了var目录文件的data block。
通过var目录的inode指针,可以寻找到var目录的inode记录,但是指针定位的过程中,还需要知道该inode记录所在的块组以及所在的inode table,所以需要读取GDT,同样,GDT已经缓存到了内存中。
4、在var的data block中记录了log目录名和其inode指针,通过该指针定位到该inode所在的块组及所在的inode table,并根据该inode记录找到log的data block
5、在log目录文件的data block中记录了messages文件名和对应的inode指针,通过该指针定位到该inode所在的块组及所在的inode table,并根据该inode记录找到messages的data block
6、最后读取messages对应的datablock
找到GDT-->找到"/"的inode-->找到/的数据块读取var的inode-->找到var的数据块读取log的inode-->找到log的数据块读取messages的inode-->找到messages的数据块并读取它们
老狼:MBR与GPTzhuanlan.zhihu.com![772586c586869288795c93e8cfc9ef8f.png](https://i-blog.csdnimg.cn/blog_migrate/e2db70230ea415ceee3679c0b40aa3f7.jpeg)