Linux----文件系统
这里写目录标题
- 一级目录
- <font color="FF00FF">1. 文件系统
- <font color="FF00FF">2. 磁盘
- <font color="FF00FF">3. 引入文件系统
- <font color="FF00FF">7. inode
- <font color="FF00FF">8. 一些问题
- <font color="FF00FF">9. 软链接
- <font color="FF00FF">硬链接
一级目录
二级目录
三级目录
1. 文件系统
没有被打开的文件是在磁盘上的,而文件系统可以找到磁盘上任意的文件
2. 磁盘
2.1 磁盘的存储结构
磁盘存储的基本单位是扇区(512字节),操作系统想修改磁盘上某个扇区的一个比特位,也要把这512字节全加载到内存里,然后进行修改再写回扇区

磁头和传动臂(机械臂杆)是共进退的,磁盘写入时是向柱面进行批量写入的
如果想把512字节写入到某一个扇区中,磁盘应该如何运动?
柱面,磁头,扇区
先让磁头锁定哪个柱面,然后磁盘旋转确定扇区,最后选择我们想要的磁头所指的那一个扇区,这种定位方式叫CHS



2.2 磁盘的逻辑结构

磁带卷起来就是同心圆,拉出来就是一个线性结构,那磁盘也可以抽象成一个线性结构,可以想象成把磁盘破个口,拉直

此时定位一个扇区只需要一个数字数组下标,所以操作系统对磁盘的管理就是对数组的管理
这样每⼀个扇区,就有了一个线性地址(其实就是数组下标),这种地址叫做 LBA

逻辑上,磁盘整体是由“柱⾯”卷起来的

所以,磁盘的真实情况是:
磁道:
某⼀盘面的某⼀个磁道展开:

柱面:
整个磁盘所有盘⾯的同⼀个磁道,即柱面展开:



OS只需要使用LBA就可以了!!LBA地址转成CHS地址,CHS如何转换成为LBA地址。谁做啊??磁盘自己来做!固件(硬件电路,伺服系统)
磁盘就是⼀个元素为扇区的⼀维数组,数组的下标就是每⼀个扇区的LBA地址。OS使用磁盘,就可以用⼀个数字访问磁盘扇区了
3. 引入文件系统
3.1 引入"块"概念
其实硬盘是典型的“块”设备,操作系统读取硬盘数据的时候,其实是不会⼀个个扇区地读取,这样效率太低,而是⼀次性连续读取多个扇区,即⼀次性读取⼀个块,一般是4096字节(8个扇区),可以调整
扇区号通常是从1开始的,而在LBA中,地址是从0开始的

拿LBA地址/8就可以得到块号
3.2 分区
把多个块放在不同区域叫分区,管理块的方式都是一样的,也就是把分区1管理好了,分区2和3也就管理好了,再把一个分区分成多个组,假如分区大小是300GB,分成10个组,每个组就是30GB,把这一个组的30GB管理好,因为每个组的管理方法一样,所以一个分区就管理好了,所以管理好组,磁盘就管理好了



Linux下的文件属性和内容是分开存储的,Block Group存储的基本单位是4kB
1. Data Blocks
1. Data Blocks里存储的是文件的内容,如果文件有17kb,那Data Blocks里就存储5个块号,最后一个块存储1kb的内容
2. inode Table
2. Linux中,任何正常文件,都要有自己的属性集合!
而这些属性在struct inode这个结构体当中,大小固定,一般是128字节,而当我们创建文件时,在内核会创建struct inode结构体,把属性填充到inode,然后再把inode写到 inode Table里
1. 文件的属性大小是一样的
2. 文件系统的载体是分区
3. 文件名不会做为属性保存在文件的inode当中
4. struct inode 里有整形类型的变量来标识文件,确定是哪个文件
5. inode table里一个数据块保存32个inode,文件系统和IO交互时,4KB,也就是一次加载32个文件
3. 块位图(Block Bitmap)
Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用,假如Data Block里有4个数据块,那Block Bitmap里就有4个比特位来记录,申请一个数据块填写文件内容时,对应的比特位就置为1,释放数据块时1置为0
4. inode位图(Inode Bitmap)
每个bit表示⼀个inode块是否空闲可用,跟块位图一样
平时下载游戏时,会很慢,因为要把游戏文件的属性写到inode Table里,内容写到Data Blocks里,然后把位图置1,而删除游戏时很快,因为只要把位图由1置为0,这块空间就是无效的,可以被覆盖掉,这也是为什么文件可以恢复,因为只要把位图再由0置1就可以了,注意这里是删除不是卸载
5. GDT(Group Descriptor Table)
块组描述符表,描述块组属性信息,整个分区分成多个块组就对应有多少个块组描述符。每个块组描述符存储⼀个块组的描述信息,如在这个块组中从哪里开始是inode Table,从哪里开始是Data Blocks,空闲的inode和数据块还有多少个等等
structext2_group_desc{ __le32 bg_block_bitmap;/* Blocks bitmap block */ __le32 bg_inode_bitmap;/* Inodes bitmap */ __le32 bg_inode_table;/* Inodes table block*/ __le16 bg_free_blocks_count;/* Free blocks count */ __le16 bg_free_inodes_count;/* Free inodes count */ __le16 bg_used_dirs_count;/* Directories count */ __le16 bg_pad; __le32 bg_reserved[3];};6. 超级块(Super Block)
存放文件系统本身的结构信息,描述整个分区的文件系统信息。
记录的信息主要有:bolck和inode的总量,未使用的block和inode的数量,⼀个block和inode的大小,最近⼀次挂载的时间,最近⼀次写入数据的时间,最近⼀次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了
知道inode Table和Data Blocks就知道整个分区的信息了
格式化的本质就是写入文件系统的管理信息,就是把Block Group里的前四个区域的内容清0
7. inode
1. inode的编号和块号,在不同组里编号不同,比如组1是1-1000,组2就是1001-2000
2. inode的编号和块号在不同分区可以重复,比如分区1是1-10000,分区2也可以是1-10000
拿着文件的inode编号就可以找到文件的所有属性和内容
按照第1点的分组情况,假如inode编号是1001
1. 首先1001/1000=1,确定分组
1001%1000=1,确定inodeBitmap中的第一个比特位的位置,然后看是否为1,为1证明是有效的文件资源,从而确定是inode Table里的第一个块,然后拿着inode编号就可以找到该文件的属性,该文件的属性inode里存在一个数组,保存着该文件对应的数据块编号(Data Blocks),根据该编号就可以拿到文件的所有内容
8. 一些问题
8.1 Linux下如何看待目录
目录也是按照上述的方式进行保存的!
目录也由inode和数据内容(Data Blocks)
目录的数据内容存放的是文件名/目录名:inode的映射关系
8.2 文件名不会作为属性,保存在文件的inode中
文件名保存在当前文件所属的目录的数据内容当中
8.3 之前没有用inode找文件,用的都是文件名
其实用的是路径+文件名,先打开文件所属的路径,读取目录对应的数据内容,得到文件名和inode的映射关系,再用inode进行文件查找
访问任何文件都必须得有路径,所以找到任何Linux文件,都必须从/目录开始,进行路径解析,直到找到对应的文件,/是操作系统默认打开的
我们访问任何文件,都必须要从根目录下进行路径解析吗?
如果这样做,就是一直在做磁盘IO,效率太低,操作系统在进行路径解析时,会把历史访问的所有路径(目录)形成一棵多叉树,进行保存,这是Linux系统的树状目录结构,它是内存级的,下次访问已存在文件直接在内存里从根目录依次打开,无需与磁盘IO,如果没有这个文件继续从根目录进行路径解析完善这棵树
Linux中,在内核中维护树状路径结构的内核结构体叫做: struct dentry
structdentry{atomic_t d_count;unsignedint d_flags;/* protected by d_lock */spinlock_t d_lock;/* per dentry lock */structinode*d_inode;/* Where the name belongs to - NULL is * negative *//* * The next three fields are touched by __d_lookup. Place them here * so they all fit in a cache line. */structhlist_node d_hash;/* lookup hash list */structdentry*d_parent;/* parent directory */structqstr d_name;structlist_head d_lru;/* LRU list *//* * d_child and d_rcu can share memory */union{structlist_head d_child;/* child of parent list */structrcu_head d_rcu;} d_u;structlist_head d_subdirs;/* our children */structlist_head d_alias;/* inode alias list */unsignedlong d_time;/* used by d_revalidate */structdentry_operations*d_op;structsuper_block*d_sb;/* The root of the dentry tree */void*d_fsdata;/* fs-specific data */#ifdefCONFIG_PROFILINGstructdcookie_struct*d_cookie;/* cookie, if any */#endifint d_mounted;unsignedchar d_iname[DNAME_INLINE_LEN_MIN];/* small names */};这里的lru算法可以清理最近最少使用的文件,从而维护内存
进程提供文件路径
8.4 分区怎么确定
分区一定要与一个特定的目录相关联,这个行为是挂载通过进入这个目录就相当于进入该分区
一个文件存在它一定在某个分区里,而分区定要与一个特定的目录相关联,所以分区确定了,这里的log.txt在xaq目录下,xaq一定会和分区进行挂载,所以分区在文件所处目录

9. 软链接

软链接后者指向前者,对log.txt进行操作就相当于对log进行操作,反之一样

软链接是独立的文件,因为它有独立的inode number,软链接就是windows 下的快捷方式,软链接的文件内容保存的是文件的路径,删除log.txt,log里面的内容没了
硬链接


硬链接不是独立的文件,因为它没有独立的inode,本质是一组新的文件名和inode number的映射关系,可以对文件进行备份,删除log.txt,log里面的内容依旧存在·
这里的2,是多一个新的文件名指向659462,硬链接数

一个空目录的硬链接数是2,而普通文件的硬链接数是1,普通文件就是自己的文件名指向inode

因为里面目录存在一个点目录指向sb,进入sb目录再新建目录,此时硬链接数变成3,因为存在…指向sb,所以一个目录的硬链接数-2,就是这个目录里存在目录的数量

Linux只能给普通文件进行建立,Linux系统不支持给目录建立硬链接,但是Linux默认用.和…进行硬链接,自己建立硬链接容易形成闭环,.和…系统特殊处理不会有闭环问题,软链接文件类型不同,系统可以识别
