文件有很多,但是被打开的文件很少,这些没有被打开的文件在磁盘中,这就叫做磁盘文件。每次先打开一个文件,需要先找到这个文件,需要通过文件路劲及文件名先在磁盘中找到这个文件。本篇文章要研究的是磁盘文件,核心问题是如何存取问题。在研究这些问题之前,需要先认识一下硬件–磁盘
磁盘本质是一个机械设备
计算机只认识二进制,即0和1,在物理层面上有不同的表现
磁盘是一个机械设备,是一个外设,速度比较慢。
磁盘读写的基本单位是扇区,512字节,4KB 1片=n磁道,1磁道=m扇区
这么多扇区,如何找到指定位置的扇区?
上述称为CHS定址法
所谓把文件存储在磁盘,本质是文件在磁盘中占几个扇区
为什么需要把磁盘的存储结构进行逻辑抽象? 一方面如果操作系统直接用CHS地址,硬件改了,那么软件也改了,耦合度过高; 另一方面方便实现内核进行磁盘管理。
在块级别上,磁盘被划分为若干个固定大小的块(通常是几KB或几MB)。文件系统会将文件分割成多个块,并将这些块按需存储到磁盘上。每个块都有一个唯一的地址,文件系统通过记录块的地址和文件的元信息(如文件大小、创建时间等)来管理文件的存储和访问。
最终一个磁盘可以看作是基于扇区的数组,每一个扇区都对应有一个下标来唯一标识。通过这个下标(LBA 逻辑扇区地址),再结合每一面磁道的个数和每一个磁道上扇区的个数就可以定位到该扇区在磁盘上的位置(CHS地址)。
通过逻辑抽象,用户和应用程序可以像操作文件一样操作磁盘上的数据,而不需要了解底层的物理存储细节。文件系统负责将逻辑操作转换为物理操作,并管理数据在磁盘上的存储和检索。这样,文件系统提供了一种方便和可靠的方式来管理和利用磁盘的存储空间。
进一步可得,所谓的文件只需要知道LBA地址,文件=很多个LBA地址(纯硬件)。
Linux文件系统特点:文件内容和文件属性分开存储 先简单了解一下文件系统:
在每一个分区内部分组,然后写入文件系统的管理数据
Linux ext2文件系统,上图为磁盘文件系统图(内核内存映像肯定有所不同),磁盘是典型的块设备,硬盘分区被划分为一个个的block。一个block的大小是由格式化的时候确定的,并且不可以更改。例如mke2fs的-b选项可以设定block大小为1024、2048或4096字节。而上图中启动块(Boot Block)的大小是确定的
ll -li
即可查看文件号我们在寻找文件的时候,需要找到inode编号 inode编号是分区为单位整体分配的,一个分区内inode编号不可能重复。两个分区的inode编号可能是重复的,因此inode不能跨分区访问。一个分组使用的inode编号,是在一个范围中;例如,第一个分组时1 ~ 10000,第二个分组是 10001 ~ 20000… 在Super Block和GDT中都会记录start_inode和end_inode,这样就能确定inode在哪一个分组里。
datablocks也是如此
目录=文件属性+文件内容 ,目录也有自己的inode属性
通过上述可见,目录和文件的属性结构是一致的
查找一个文件,是根据该文件的文件名在系统中找到该文件对应的inode编号。
因此可以解释一下现象:
首先创建文件一定是在一个路径下(目录)进行创建,这个路径就会帮我们定位到一个分区,然后去从第一个分组开始查看当前分组的 GDT 字段,看该分组中 inode 的使用情况,若当前分组中的 inode 还有剩余,接着去读取 inode_Bitmap,获取最近一个未被使用的 inode 编号,然后拿着 inode 编号去 inode_Table 里面找到对应的 inode,将文件的属性信息一填。如果有文件内容,先拿着 inode 编号找到对应的分组,根据写入内容的大小去 Block_Bitmap 中找出对应数量未被使用的块号,然后将这些块号写入到 inode 对应的属性里面,然后拿着块号去 Data blocks 中进行写入。
删除文件只要拿着该文件的 inode 编号,在 inode Table 中找到对应的 indoe,获取到里面的 blocks,即拿到该文件对应的所有块号,然后根据这些块号将 Block Bitmap 中对应的比特位置0(假设 0 表示对应的块未被使用)。最后再根据 inode 编号到 inode Bitmap 中将该 inode 对应的比特位置为0,至此,一个文件就被删除啦。可以发现从头到尾并没有去修改块中的内容,这也是为什么拷贝 4G 的文件很慢,删 4G 的文件很快。所以在理论上,一个被删除的文件,可以根据 inode 将其恢复出来。