当前位置: 首页 > Linux

【Linux系统】文件系统(二)——文件读取流程

时间:2023-04-06 01:38:07 Linux

前言在上一篇【Linux系统】文件系统(一)——磁盘基础知识中,主要介绍了一些存储文件的磁盘的基础知识。对于Linux系统,所有数据都源自存储在磁盘上的文件。Linux文件系统是如何构建和存储在磁盘上的?操作系统如何找到这些文件来读取?本章主要介绍这些问题(以Ext2文件系统(传统linux文件系统)为例)。Linux系统目录树linux文件系统中的所有文件和目录都从根目录开始,以树的形式展开,如下图所示:根据FHS的基本定义,每个目录(如usr、var)根目录下基本上各有其特定的含义,这里就不介绍了。重点关注根目录'/'的作用和意义:其他所有目录都是从根目录派生出来的。根目录包含引导软件、系统内核文件、函数库、文件系统修复程序等,因此根目录(/)所在的分区尽量小,应用程序安装的软件不要存放在与根目录相同的分区中。根目录越小,系统性能越好,根目录所在的文件系统越不容易出问题。文件(目录)存储方式在Linux中,磁盘(硬盘)上的存储分区如下图所示:MBR:主引导分区。引导块(BootSector):分区中存放文件系统自身引导程序的地方。超级块(Superblock):记录整个文件系统相关信息的地方。它记录的信息主要包括:块和inode的总量、使用量、剩余量,文件系统的挂载时间,最后写入数据的时间等。柱面组(blockgroup)每个柱面是一个柱面组(组号与柱面号一致),一个分区包含多个柱面。配置信息:未知。i节点位图(inodebitmap):每个inode节点对应位图中的一个bit(这样一个字节可以表示8个inode的使用情况),每个bit的值为0或1,表示该bit的位置是否对应inode使用下标。块位图:每个数据块或目录块对应块位图中的一个位。比特的下标与块号一一对应。每一位的值为0或1,表示该块已被使用。i-nodetable(array)(索引节点表):每个文件或目录都有对应的索引节点,索引节点放在索引节点表中,包括索引节点的编号及其对应的信息。I节点(inode):存放文件相关信息(不包括文件名)。数据块(datablock):存放文件的具体内容。目录块:一个特殊的数据块,存放inode号--文件(目录)名。inode详解inode主要记录了文件的属性以及文件的实际数据放在了第几个数据块(或目录块)中。具体包括以下信息:文件访问模式(r/w/x)、文件所有者和组(owner/group)文件大小文件创建时间或状态改变时间(ctime)最后读取时间(atime)最近修改时间(mtime)flag定义文件特征(flag)真实指向的数据块文件的内容(指针)另外,inode的特点是:inode的数量和大小在磁盘格式化时是固定的,除非重新格式化并重新设置,否则无法更改。每个inode的大小为128Bytes。每个文件只占用一个inode。文件系统可以创建(存储)的文件数量与inode数量和磁盘大小(数据块数量)有关。系统在读取文件时,首先需要找到inode,分析inode记录的权限是否与用户的权限相匹配。如果匹配,则可以真正读取数据块中的内容。为了解决inode数量可能不够的问题,操作系统将inode记录块号的区域定义为12个直接、1个间接、1个双间接、1个三重间接记录区域。文件IO编程中经常提到的文件句柄,其实就是inode号。文件读取过程以读取文件/var/log/message为例,说明读取文件messages时从磁盘中查找/读取文件内容的过程。首先,系统通过挂载信息(在超级块中,位置固定)找到根目录(/)的inode号,根目录对应的inode号是固定的(通常为2号)。根据根目录的inode号(2号),在inode表中找到对应的inode信息,从inode信息中找到存放根目录信息的目录块号,根据编号找到数据块,如图中标有'/'的方块,目录块中存储的信息如图中的dentry。从目录块存储的信息中,找到文件名(目录名)var对应的inode号(2667711)。在inode表中找到编号为2667711的inode信息,从inode信息中找到var目录下存放的数据块。从var数据块存储的信息中,找到日志目录对应的inode号(267850)。重复以上步骤,直到找到消息文件对应的inode节点,根据inode节点记录的消息文件内容对应的数据块,从数据块中读取内容。扇区、块(簇/数据块)、页在操作系统的数据交互过程中,经常会听到扇区、块(簇/数据块)、页这些单位。它们在数据交互过程中的含义是:扇区:磁头从磁盘读取数据的最小单位,即磁头每次从磁盘读取数据时,一次读取一个扇区。块(cluster):操作系统与磁盘(硬盘)交互的最小数据单位(在linux系统中称为block,在windows系统中称为cluster)。操作系统从硬盘中取出一段数据,即完成一次磁盘IO。block(数据块)大小是在硬盘格式化时指定的,一般有1K、2K、4K(最常用)。如果块大小设置为4K,那么在将数据块传递给操作系统之前,磁盘将读取8个扇区。另外,数据块也是DOS下数据存储的最小单位。例如,如果一个文件大小为1K,块大小为4K,文件仍然占用一个块,块中剩余的3K是空闲的,不能用来存储其他数据。因此,在设置块大小时,需要考虑要存储的文件的大小。页:操作系统访问内存时的最小单位,一般系统页大小为4K(或更大)。操作系统在访问内存中的数据时,如果发现内存中没有可以提供该数据的页面,就会出现页面错误,系统会通过页面将数据从硬盘读取到内存中替换(从硬盘读取数据)页面,然后返回给调用者。一般来说,主要原因是不同的系统和设备在设备之间交换数据时使用不同的机制和概念。内部磁盘时(磁盘驱动程序从磁盘读取数据),单位为扇区;操作系统从磁盘读取数据时,单位是块;操作系统从内存中读取数据时,单位是页。操作系统对文件访问操作的优化并没有为每个文件读写操作实际从磁盘读取或写入,因此性能是不可接受的。为此,操作系统采用了一系列机制来提高文件IO的性能。缓存无论是硬盘还是操作系统,都会缓存从磁盘读取的数据。硬盘中的缓存一般比较小,比如十几M,而操作系统中的缓存可能会大很多。系统会将常用的??文件数据放入主存的缓冲区中,以加快文件系统的读写速度。一般情况下,只要系统有足够的内存,系统就会尽可能多地将磁盘上常用的文件缓存到内存中,直到内存耗尽(这是正常现象)。比如你发现电脑读取文件的速度达到每秒2G,那肯定不是真的从磁盘读取,而是从缓存读取。所以要测试从磁盘读取数据的真实速度,需要先清除系统的缓存。异步处理当系统加载一个文件到内存中时,如果文件没有被改变,内存段中的文件数据将被标记为clean,如果已经被改变,则被标记为dirty。此时,所有的文件操作仍然在内存中进行,并没有写入磁盘。系统会时不时地将内存中的脏数据写回磁盘,以保持磁盘和内存数据的一致性。这个过程是异步的。也可以使用sync命令强制将内存中的数据写回硬盘。另外需要注意的是,在正常关机的情况下,关机命令会主动调用sync将内存中的数据写入磁盘。disk,因此重启可能需要很长时间进行磁盘验证,甚至可能导致文件系统损坏(非磁盘损坏)。综上所述,本文从里到外详细讲解了Linux系统文件的读取过程,已经进入了Linux操作系统的层面。在下一篇文章中,这些原理可能会结合文件IO系统调用函数来讲解。从而完成硬件-系统-应用的完整过程。