文件(file)2————inode简介与文件的读取
文件1从需求的方面对文件系统进行了概述,这一篇文章我们以鸟哥的书来讲述文件系统,从磁盘组成与分区到文件系统。
1、磁盘组成与分区
扇区(Sector)为最小的物理存储单位,依据磁盘的设计不同分为512Byte和4K两种格式。将扇区组成一个圆,那就是磁柱(Cylinder)。
早期的分区主要以磁柱为最小分区单位,现在的分区通常使用扇区为最小分区单位(每个扇区都有其号码),磁盘分区主要有两种形式MBR和GPT。MBR分区表中第一扇区最重要里面有MBR以及分区表(patition table),其中MBR占446Byte而partition table占64Btye。GPT分区除了分区数量扩充较多之外,支持的磁盘容量也可以超过2TB。更多详情可以看另一篇微博关于Linux磁盘分区与双系统 。如果觉得还是不够详细可以参考鸟哥书的第二章。
所有的实体磁盘都被模拟成/dev/sd[a-p]。而分区槽的档名若以第一颗磁盘为例,则为/dev/sda[1-128]。虚拟机的磁盘格式为/dev/vd[a-p]。若使用了软件磁盘阵列的话,那么还有/dev/md[0-128]的磁盘文件名。使用LVM时,则档名为/dev/VGNAME/LVNAME等格式。
2、文件系统特性
磁盘分区结束后,需要进行格式化(format)之后OS才能够使用这个文件系统。为什么要格式化?因为每种OS所设定的文件属性/权限并不相同,为了存放这些文件所需的数据,因此需要将分区槽进行格式化,以成为OS能够利用的文件系统格式。具体而言,windows98之前的操作系统主要利用的文件系统是FAT(或FAT16),windows2000以后的版本有所谓的NTFS文件系统。至于Linux的正统文件系统则为EXT2(Linux Second extended file system,ext2fs)这一个。默认情况下windows是不认识EXT2的。
在传统的磁盘与文件系统之应用中,一个分区槽就是只能够被格式化成为一个文件系统,所以我们可以说一个filesystem就是一个partition。如今,有了LVM与软件磁盘阵列(software raid),这些技术可以将一个分区槽格式化为多个文件系统(LVM),也能够将多个分区槽合成一个文件系统(LVM,RAID)。所以说,目前我们在格式化时已经不再说成针对parpartition来格式化,通常我们可以称呼一个可挂载的数据为一个文件系统而不是一个分区槽。
Linux OS的文件权限(rwx)与文件属性(owner,gourp,time等参数)都属于一个文件的属性,会存放在iNode中,至于实际的数据则存放到data block区块中。另外还有一个超级区块(superblock)会记录整个文件系统的整体信息,包括iNode与block的总量、使用量、剩余量。
每个iNode和block都有编号,至于这三个数据的意义可以简略说明如下:
superblock :包含metadata,metadata定义了其他文件系统结构以及放置他们的物理磁盘分区; 记录此filesystem的整体信息,包括inode/block的总量,使用量,剩余量,以及文件系统的格式与相关信息。
inode : short for index-node,一个文件占用一个inode,同时记录文件的数据所在的block号码。
block : 实际记录文件的内容,若文件太大时,会占用多个block。
3、Linux的EXT2文件系统(iNode)
Linux文件系统EXT2使用这中iNode为基础的文件系统。文件系统一开始就将iNode与block规划好,除非重新格式化(或者利用resize2fs等命令变更文件系统大小),否则iNode和block固定后就不再变动。
但是仔细考虑,如果我的文件系统高达数百GB,那么所有的iNode和block统统放在一起将不好管理,因此EXT2文件系统在格式化的时候基本上是区分为多个区块群组(block group)的,每个区块群组都有独立的iNode/block/superblock系统。
整体来说EXT2格式化后有点像底下这样:
在整体的规划当中,文件系统最前面有一个启动扇区(boot sector),这个启动扇区可以安装开机管理程序。因为这个设计,我们就可以将不同开机管理程序安装到个别的文件系统最前端,而不用覆盖整颗磁盘唯一的MBR,这样一来才可以制作多重引导。
DATA BLOCK:
在EXT2文件系统中所支持的block大小有1K,2K及4K三种而已。由于block大小的差异,会导致该系统能够支持的最大磁盘容量与最大单一文件容量并不相同。因为block大小而产生的EXT2文件系统限制如下:
Block大小 1KB 2KB 4KB
最大单一文件限制 16GB 256GB 2TB
最大文件系统总容量 2TB 8TB 16TB
另外基本限制如下:
原则上,block的数量与大小在格式化完了就不能再改变了;每个block内最多只能够放置一个文件的数据;如果文件大小大于block大小,则一个文件就会占用多个block;反之,如果小于。则该block的剩余容量就不能够再被使用了。(磁盘空间会被浪费)
举个例子:假设你的EXT2文件系统使用4K block,而文件系统中有10000个小文件,每个文件大小为50Bytes,请问此时你的磁盘浪费多少容量?
(4096-60)*10000Bytes=38.6MBytes 而这些文件总大小为10000*50=500000Bytes=0.47MBytes, 一个不到1M的总文件量会浪费将近40MB的容量,且文件越多造成的浪费越大。
iNode table :
对于iNode(short for index-node)记录的文件数据至少包括:该文件的存取模式(RWX),该文件拥有者与组群(owner/group),该文件的容量,该文件建立或状态改变的时间(ctime),最近一次的读取时间(atime),最近一次修改时间(mtime),该文件特性的旗标(flag)如SUID,该文件真正内容的指向(pointer);
另外iNode的数量和大小也是在格式化的时候已经固定了,每个iNode大小均为128Bytes(新的ext4和xfs可设定为256bytes);每个文件都只有一个iNode;因此文件系统能够建立的文件数量与iNode的数据有关,系统读取文件时需要先找到iNode,并分析iNode所记录的权限与用户是否符合,若符合才能够开始实际读取block内容。
iNode需要记录的数据很多,而iNode记录一个block号码要花掉4byte。假设一个文件有400MB且每个Block 4K时候,那么至少需要十万block,iNode并不可能记录这么多信息。系统将iNode记录block号码的区域定义为12个直接,一个间接,一个双间接与一个三间接记录区。其中所谓的间接就是再拿一个block来当作记录block号码的记录区,如果文件太大时,就会使用间接的block来记录编号。同理如果文件持续长大,那么就会利用所谓的双间接,第一个block仅再指出下一个记录编号的block在哪里,实际记录在第二个block当中,以此类推,三间接就是第三层block来记录编号。关于更多的inode pointer structure on Wikipedia。
所以 假设为1K block
总额=[直接(12)+间接(1K/4=256)+双间接(256*256)+三间接(256*256*256)](个block) * 1K(一个block 1K)=16GB 这个是能够容纳的最大文件容量。
superblock:(大小1024Bytes,使用dumpe2fs指令来呼出观察)
superblock是记录整个filesystem相关信息的地方,他主要记录的信息有:
block和iNode的总量;未使用/已使用的iNode/block数量;block与iNode的大小(block为1,2,4K,iNode为128bytes或256bytes);filesystem的挂载时间、最近一次写入数据时间、最近一次检验磁盘(fsck)的时间等文件系统的相关信息;一个valid bit 数值,若此文件系统已被挂载,则valid bit为0 否则为1。
filesystem description:每个区段可以描述每个block group的开始与结束的block的号码,以及说明每个区段(superblock,bitmap,inodemap,data block)分别介于哪一个block号码之间,使用dumpe2fs来观察。
block bitmap(区块对照表):记录block的变动,删除文件空出来;iNode bitmap,是类似的关系;dumpe2fs:查询Ext家族superblock信息的指令;blkid:这个指令可以叫出目前系统有被格式化的装置
4、文件系统与目录树的关系
目录:
当我们在Linux下的文件系统建立一个目录时,文件系统会分配一个iNode与至少一个block给该目录。其中,iNode记录目录的相关权限与属性,并可记录分配到哪块block号码;而block在记录在这个目录下的文件名与该文件名占用的iNode号码数据。如果实际想观察文件所占用的iNode号码,可以使用 ls -i 这个选项来处理。
iNode number | 文件名
53735697 | anaconda-ks.cfg
....... | ......
文件:
当我们在Linux下的ext2建立一个一般文件时,ext2会分配一个iNode与相对于该文件大小的block数量给该文件。
目录树读取:
举个例子 读取 /etc/passwd:
1、/的iNode:透过挂载点的信息找到iNode号码为2的根目录iNode,且iNode规范的权限让我们可以读取该block的内容(有r与x);
2、/的block:经过上个步骤取得block的号码,并找到该内容有etc/目录的iNode号码(2883585)
3、etc/的iNode:读取2883585号的iNode得知ssozh具有r与x权限,因此可以读取etc/ 的block内容;
4、etc/的block:经过上个步骤取得的block号码,并找到该内容有passwd文件的iNode号码(2883788);
5、passwd的iNode:读取2883788号iNode得知ssozh具有r权限,因此可以读取passwd的block内容;
6、passwd的block:最后将该block内容读取出来。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix