磁盘与文件系统
前面学的是从进程角度看待文件操作系统不会区分你写的是字符还是二进制调用的参数全是void*实际上是语言用户区分。文件操作使用语言操作除非特殊情况用系统调用上面谈论的是文件被打开之后会发生什么概括用户层-分配fd语言层-语言级缓冲区操作系统-页面缓冲磁盘-保存你这次的记录文件ownergroupother时间戳是否重新编译看obj和.c文件的时间戳比较文件大小物理位置打开模式,r,w,a下面讲文件未被打开磁盘级文件系统理解硬件磁盘的物理结构如何把数据写入到扇区定位扇区LBA实际情况:CHS寻址法LBA vs CHSCHS转成LBALBA转成CHS引入文件系统磁盘管理如何管理(inode Table)inode属性和内容如何关联(储存数据Data Blocks)判断Data Blocks数据块是否被使用Block Bitmap位图判断 Inode Table的块是否被使用Inode Bitmap位图GDTGroup Descriptor Table超级块Super Block文件的增删查改文件名问题1问题2重谈inode编号和块号的联系inode和datablock映射(弱化)数组储存数据时可以学习这种思想问题3路径缓存问题1问题2问题3问题4总结磁盘级文件的保存由磁盘级文件系统决定理解硬件机械磁盘是计算机中唯⼀的⼀个机械设备• 磁盘— 外设• 慢冯诺依曼• 容量大价格便宜这是一个机械硬盘内部的结构是在大型企业中我们经常看到这个服务器机箱这些格子里面储存到就是机械硬盘这个就是机柜里面可以防止多个服务器机箱后面有多根线是网络跳线用于传输网络数据我们想想看计算机当中的01到底是什么其实是把磁铁中的南极定义0,北极定义成1当你存入数据的时候磁盘中会有弱电由电磁感应效应产生磁场翻转南北级就实现了改变01所以就能储存信息所以彻底删除数据削磁或者把磁铁全部置为0或1削磁高温即可磁盘的物理结构磁盘的理论图是这样的看起来你光滑的但实际上是一圈圈的这一圈圈的叫做磁道磁道也不是连续的是有扇区和间隙看图b,有多个磁头所有磁头共进退所有盘片共旋转这里这个红色的部分就是对应的扇区扇区是磁盘存储数据的基本单位512字节块设备现在主流的有4k的基本单位读或者写磁盘的时候必须是512为单位的所以想从内存级缓冲区刷新到磁盘中必须要够512字节才可以柱面看到那个类似圆柱的形状了嘛那个就是细节离圆心越远扇区的r起来越小是因为满足都是512字节如何把数据写入到扇区如何找到对应位置的扇区1.2.a.先确定在哪一面-磁头编号b.在当前面中在哪一个磁道中c.确认在当前磁道中在哪一个扇区文件内容属性数据两者都是数据无非就是在扇区中储存定位扇区LBA想象一下把上面那个光滑的盘面任意切一刀再拉直这样每一个扇区就有了一个线性地址(其实就是数组下标)这种地址叫做LBA实际情况:CHS寻址法磁盘在进行访问的时候先确定我们要访问哪一个柱面然后在通过磁盘旋转找到对应扇区最后找到扇区之后还有多个面确定是哪个面——磁头编号磁盘是由柱面构成的帮助理解磁头摆动的意义本质是访问哪一个磁道或者柱面盘片旋转的意义为了让磁头定位到扇区读取一个扇区选定哪一个磁头即可上面有三个变量能不能把他定义成三维数组呢可以的柱面的变量定义为第一维度磁头定义为第二维度扇区定义为第三维度所以磁盘的本质就是一个三维数组在磁盘中定位扇区又可以有新的理解了1.柱面第一维cylinder,相当于磁道2.磁头第二维选择哪一面,head3.扇区第三维,sector这就是CHS寻址法本质就是数组下标OS只需要使用LBA就可以了LBA vs CHS定义每磁道扇区数每个磁道所有的扇区数量的总和柱面号C (他是在哪个柱面不是柱面总数半径)扇区号S (这个扇区的数组下标CHS中是不存在下标0的)“//”:表示除取整磁头数有多少个盘面磁头号H (在哪一层)柱面号磁头号LBA都是从0开始的磁头数 *每磁道扇区数单个柱面的扇区总数(一个盘面有多少个扇区)总扇区/单个柱面的扇区总数磁道数CHS转成LBA磁头数每磁道扇区数单个柱面的扇区总数LBA 柱面号C * 单个柱面的扇区总数他所在的这个面不算他所在的磁道有多少个扇区磁头号H每磁道扇区数在他上面的面有多少个磁道扇区号S -1LBA转成CHS本质一维数组下标转化为三维柱面号C LBA //(磁头数* 每磁道扇区数)磁头号H (LBA %(磁头数* 每磁道扇区数))走过来多少个扇区//每磁道扇区数扇区号S (LBA %每磁道扇区数)1(不存在下标0)先看LBA转CHS的第一条公式LBA除以一个柱面的扇区数商得到他是在第几磁道余数还剩下多少个扇区我只要商就是得到在第几磁道也叫做柱面号再看第二条公式LBA取模一个柱面的扇区数得到的是还剩下多少个扇区而这些扇区是应该分配在这个柱面上的每一个面应该分配的就是每磁道扇区数所以这两个整除取商不就是应该在第几个面嘛第几个面就是磁头号呀第三条公式LBA除以每磁道扇区数就是看他可以填满多少个磁道取余就是剩下的还不能填满这个磁道我要看他具体能填到哪里加一是因为CHS不存在下标0所以要加1好现在做一道题目了解了解好我现在要插入到粉色的第二个他的LBA应该是15(蓝色是0到15),2(粉色两格)得到LBA17先求柱面C:磁头数2(盘面数量是2)* 2(一个盘面有两边)4每磁道扇区数4C17//(4*4)1;第二个格子确实是在柱面1正确再求磁头号(17% ( 4 * 4))1;1//40;说明他在第一面注意有很多人看图就会说这不应该是在第三面嘛注意最下面的是柱面蓝色的0-3是分配到第一面的第一磁道的蓝色的4-7是分配到第二面的第一磁道的同理粉色的0-3是分配到第2磁道的第一面的。正确第三:17%41112正确这个工作是磁盘自己做的磁盘就是一个元素为扇区的一维数组数组的下标就是每一个扇区的LBA地址。OS使用磁盘就可以用一个数字访问磁盘扇区了。所以如何写入数据呢引入文件系统硬盘的每个分区是被划分为一个个的”块”。一个”块”的大小是由格式化的时候确定的并且不可以更改最常见的是4KB即连续八个扇区组成一个”块”。”块”是文件存取的最小单位。为什么操作系统不以扇区为单位呢1.提高效率2.软硬件解藕不想磁盘和操作系统有关联磁盘管理假设你有一个800G的磁盘他要对这内存800G的进行管理是先进行分区再进行分组管理结论1文件内容属性-linux系统中文件的内容和属性分开储存的结论2一个组里面包含了文件数据和管理文件数据的信息(都是数据)写入管理信息的过程叫做写入文件系统也叫做格式化是在分区后的如果是按照上面那种分组是在分组前的只有先格式化才能分得清组1组2组3注如何确定你在哪一个分区呢格式化本质是写入管理信息写入完之后无法直接写入信息的必须把你指定的分区或者文件系统挂载到指定目录下才可以写入信息你的文件要访问是要有路径的可以通过路径判断是否在哪个分区。采用最长前缀匹配。如果是按照底层物理实现如以8扇区为1Block单位则格式化与8扇区一块是同步的格式化这一动作本质上就是在执行物理空间划分和分组两者同步发生的。如何管理(inode Table)文件管理信息放在图片中的前4个Data Blocks就是物理底层以8扇区为1块,这个Data Blocks储存着所有数据每一个Data Blocks都有属于他的编号文件的属性储存在一个结构体struct inode(这个是写在inode Table里面的){//文件的所有属性就是指令ll//固定128字节基本所有的属性都是int类型的int inode;}文件inodeData Blocks文件名不属于文件inode的属性理论上一个文件一个inode,整个分组可能会存在很多文件每个文件都会存在int inode编号inode table也是由4kb的块组成的一个文件128字节4096/128,所以在一个inode表中可以储存32个文件的属性这32个文件的inode的值是不一样的。inode属性和内容如何关联(储存数据Data Blocks)在inode属性中存在一个变量会记录下来用到Data Blocks中用到哪几个数据块__le32 i_block[EXT2 _N_BLOCKS];/* Pointers to blocks */在一个分组里面找一个文件根据文件的inode number,找到对应的inode结构体再通过结构体里面的上面的成员找到对应的Data Blocks判断Data Blocks数据块是否被使用Block Bitmap位图Block Bitmap中记录着Data Block中哪个数据块已经被占用哪个数据块没有被占用4096* 832768也就是一个块可以管理32768个Data Block是否被使用判断 Inode Table的块是否被使用Inode Bitmap位图每个bit表示一个inode是否空闲可用。在linux中如何删除文件把Inode Bitmap置0把Block Bitmap置0在linux中如何创建文件申请inode属性把Inode Bitmap第一个为0的属性置为1初始化Inode Tablel,分配Block BitmapGDTGroup Descriptor Table前面4个储存的是组内部的一个组的信息是储存在GDT里面的也叫块组描述符表描述块组属性信息。每个块组描述符存储一个块组的描述信息如在这个块组中从哪里开始是inode Table从哪里开始是Data Blocks空闲的inode和数据块还有多少个等等。块组描述符在每个块组的开头都有一份拷贝。超级块Super Block刚才讨论的都是以组为单位的但我们知道一个区是有多个组的那这个区的信息储存在哪里呢没错就是储存在Super Block里面的他存放文件系统本身的结构信息描述整个分区的文件系统信息。记录的信息主要有bolck 和inode 的总量未使用的block和inode 的数量一个block和inode 的大小最近一次挂载的时间最近一次写入数据的时间最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏可以说整个文件系统结构就被破坏了理论上一个分区只需要一个super Block就好了为什么看起来每个组的都有super block呢不是每一个组都有super Block的而是有23个组有super block点这是为了防止物理坏道、突然断电或误操作而损坏相当于备份的做作用了文件的增删查改在磁盘的某一个组里面如何创建一个文件touch 创建进程调用系统函数来创建文件内存中有临时的inode属性这个是在内存级缓冲区然后操作系统在组里面查找inode Bitmap,找第一个为0的位置然后在对应下标的inode table放入属性(这里是磁盘中的内存)后面如果写入数据在block Bitamap查找第一个0的对应下标的Data Block的数据块放入元素在磁盘的某一个组里面如何删除一个文件需要先知道inode编号在你这个分组里面在inode bitmap查看对应的位置是否是1文件是否存在然后去inode Table通过下标找到对应的inode结构体包含了所有的属性把inode对应查找Data block下标的数组里面的编号拿出来再把Block Bitmap对应的位置置0。在磁盘的某一个组里面如何修改一个文件把磁盘中文件对应的属性加载到内存级缓冲区中在内存级缓冲区中修改然后再加载到磁盘中无法直接在磁盘中直接修改哦修改属性同理通过inode然后找到对应的inode table中的inode结构体再找到对应的数据块然后文件会加载到内存级缓冲区中你再通过fd找到进行修改在磁盘的某一个组里面如何查看一个文件文件内容属性必须要先知道inode在inode bitmap查看对应的位置是否是1文件是否存在然后去inode Table通过下标找到对应的inode结构体包含了所有的属性再从中找到你想要的属性文件名我们在linux中操作一直用的是文件名但是文件名却不在inode结构体内部保存那操作系统是如何找到对应的inode编码呢这里我们就要提到目录了如何理解目录呢在linux下一切皆文件目录当然也是文件文件内容属性属性里面和普通文件没区别但是内容储存什么呢他的内容是当前目录所包含的文件名和inode编号的映射表这两者都是数据可以保存在同一个数据块当中当你输入了文件名的时候就在对应的数据块里面找到对应的inode编号问题1在磁盘和文件系统的角度储存目录和储存普通文件有区别吗没有区别只是数据块里储存的内容不同理解linux下一切皆文件问题2目录的r w x权限是如何实现的目录内容里保存的是当前目录下的文件名和inode number的映射关系当没有r权限你又想往这个文件里面写入的时候先通过文件名找到对应的inode编码然后在通过inode找到inode结构体发现没有r权限返回。所以同一个目录下文件名不能重复。说到这里可能就会和页表记混了前者的对象是磁盘上的文件后者如下图对象是进程里面的变量的权限。重谈inode编号和块号的联系首先inode编号和块号不是只有组内有效而是整个分区有效但是不能跨分区。其次在一个分区内部一个文件系统内部有多少个inode有多少个数据块都是固定的都是提前设计好的。举例通常情况下每 16KB 的磁盘空间会分配 1 个 inode。假定一个分区有16G16GB16×1024×1024×16KB系统会计算出需要分配大约 1,048,576 (约 100 万) 个 inode。这意味着在这个 16GB 的分区里你最多只能创建 100 万个文件哪怕这些文件全是空文件0字节只要 inode 用完了你就再也无法创建新文件了。当然不止文件创建数量有上限文件的大小也是有上限的如果本组的 Data Blocks 满了文件的数据块可能会被分配到其他组的 Data Blocks 区域。所以单个文件的上限 Min(文件系统理论上限, 分区实际剩余空间)。每个分区的inode都是从1开始计算的每个分区的分组的inode是连续的例如在第一分区中组1的inode的编号可能是1-10000,组2的inode编号可能是10001-20001想确定在哪个组可以把inode//10000就得到他在哪个分组当然inode分配是趋向连续的他的分配规则是和fd相同的。inode和datablock映射(弱化)数组储存数据时可以学习这种思想• inode 内部存在le32 i_block [EXT2 _N_BLOCKS];/* Pointers to blocks */,EXT2 _N_BLOCKS 15,就是用来进行inode和block映射的• 这样文件内容属性就都能找到了但是看数组只有15大小的空间可能有人就认为怎么储存得下大文件呢这个inode结点下储存对应数据块的数组前12个是储存着直接下标可以直接通过地址访问到对应的数据块而131415是分别储存着一级指针二级指针三级指针通过多次解引用可以扩大实际储存的数据块数量从而实现了数组只要15个大小就可以储存全部都数据块。所以块内不止储存文件自己的数据也可以储存自己文件用到的更多的块号问题3我如何找到当前目录的inode他只有当前目录下文件名和对应的inode,可没有当前目录的inode举例假设你要往test里面写入代码首先你要先知道code的inode这样才能访问到test的inode递归你要想知道code的inode你要先知道lesson30的inode,到最后你要知道根目录/的inode这算是递归出口。所以linux的根目录是直接的固定的直接能让我们访问到的当我们要访问任何文件的时候linux内核都要为我们左从/(根目录)开始的路径解析。当然每次都这样子从头到尾找太慢了linux对用户访问过的路径是会做路径缓存的。linux要对你访问过的路径进行管理要先描述再组织。如果缓存中没有储存对应的strcut dentry结构体 目录被打开都会创建自己的struct结构体路径缓存Linux中在内核中维护树状路径结构的内核结构体叫做struct dentry当然这是多叉树用的兄弟结点法struct dentry{//这里会有一个指针指向自己的inode结构体}如果你这里要用到code和test,就会创建对应的多叉树把这些结点插入进去这个多插树会在内存里面常驻当然前面学过linux目录结构前者是后者的子集问题1这颗多叉树会动态变化嘛会动态变化在内存中有进有出因为会储存一个最近用得最少的结点。问题2只有目录才会有dentry嘛不是普通文件也有dentry,只是是目录的叶子结点每一个被访问的结点都要有dentry包括普通文件。例如我要访问/usr/src我一开始什么都没有我就会访问/usr再找到src,此刻这个多叉树里面就有usr了下次我想找/usr/local我就可以遍历这个多叉树发现树里面有usr可以直接从usr下面开始找了就不用从根目录开始找了问题3搜索的时候第一次可能卡顿第二次就快了因为路上的路径已经被缓存了。所以访问文件一定要有路径问题4相对路径呢确认当前路径是否在多叉树里面如果在就以当前路径开始找如果当前路径不在从进程pcb识别当前路径从根目录开始找当前路径。总结int fdopen(“log.txt”,xxxx);我们打开这个文件我们需要对这个文件进行路径解析与缓存创建对应的inode结构体和数据块。在内核创建对应的struct file然后在这个struct file结构体里面有个成员是strcut* dentry指向自己所对应的路径缓存指向自己目录树中的缓存结点而在dentry中找到inode,就能找到磁盘中对应的数据和属性。访问任何文件都要做路径解析和路径缓存的直到解析到这个文件。可是路径是谁提供的• 你访问文件都是指令/工具访问本质是进程访问进程有CWD进程提供路径。• 你open文件提供了路径可是最开始的路径从哪里来• 所以Linux为什么要有根目录,根目录下为什么要有那么多缺省目录• 你为什么要有家目录你自己可以新建目录• 上面所有行为本质就是在磁盘文件系统中新建目录文件。而你新建的任何文件都在你或者系统指定的目录下新建这不就是天然就有路径了嘛• 系统用户共同构建Linux路径结构.