<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<atom:link href="http://gentoo-zh.org/extern.php?action=feed&amp;tid=27&amp;type=rss" rel="self" type="application/rss+xml" />
		<title><![CDATA[Gentoo中文社区 / 文件系统（2）——文件读取过程]]></title>
		<link>http://www.gentoo-zh.org/viewtopic.php?id=27</link>
		<description><![CDATA[文件系统（2）——文件读取过程 最近发表的帖子。]]></description>
		<lastBuildDate>Thu, 04 Aug 2022 14:55:18 +0000</lastBuildDate>
		<generator>FluxBB</generator>
		<item>
			<title><![CDATA[文件系统（2）——文件读取过程]]></title>
			<link>http://www.gentoo-zh.org/viewtopic.php?pid=27#p27</link>
			<description><![CDATA[<p>前言</p><p>在前面的文章【Linux系统】文件系统（1）——磁盘的基本知识中，主要对存储文件的磁盘的一些基础知识进行了介绍。对于Linux系统来说，一切的数据都起源于磁盘中存储的文件。Linux文件系统的结构及其在磁盘中是如何存储的？操作系统是怎样找到这些文件进行读取的？这一章主要围绕这几个问题进行介绍（以Ext2文件系统（传统的linux文件系统）为例）。<br />Linux系统目录树</p><p>linux文件系统所有文件和目录都是由根目录开始的，以树的形式展开，如下图所示：</p><p>根据FHS的基本定义，根目录下面的各个目录（如usr，var）基本上都有其特定的意义，在此不多做介绍。重点说一下根目录&quot;/&quot;的作用和意义：</p><p>其他所有目录都是由根目录衍生出来的。</p><p>根目录中包含了开机软件、系统内核文件、函数库、文件系统修复程序等。</p><p>因此，根目录（/）所在的分区应该越小越好，应用程序所安装的软件最好不要与根目录存放在同一个分区。根目录越小，系统性能会更好，根目录所在的文件系统也较不容易出现问题。<br />文件（目录）存储方式</p><p>linux中，磁盘（硬盘）上的存储划分如下图所示：</p><p>MBR： 主引导分区。</p><p>自举块（引导分区Boot Sector）：分区中文件系统自身引导程序存放的地方。</p><p>超级块（Super block）： 记录整个文件系统相关的信息的地方，它记录的信息主要有：block与inode的总量、使用量、剩余量，文件系统的挂载时间，最近一次写入数据的时间等。</p><p>柱面组（块组） 每个柱面为一个柱面组（组号与柱面号一致），一个分区包含多个柱面。</p><p>配置信息：不详。</p><p>i节点位图（inode bitmap）：每个inode结点对应位图中的一个位（这样一个字节可表示8个inode的使用情况），每个位值为0或1，表示该位所处下标对应的inode有没有被使用。</p><p>块位图（block bitmap）：每个数据块或目录块都对应着块位图中的一个位，位的下标和块编号一一对应，每个位的值为0或1，表示该块是否已被使用。</p><p>i节点表（数组）（inode table）：每个文件或者目录都有对应的一个inode，inode放在inode table中，包括inode的编号及其对应的信息。</p><p>i节点（inode）： 存储文件相关信息（不包括文件名）。</p><p>数据块（data block）： 存储文件具体内容。</p><p>目录块： 特殊一点的数据块，存放inode编号--文件（目录）名。<br />inode详解</p><p>inode的主要记录了文件的属性以及该文件实际数据是放在哪几号数据块（或目录块）中，具体包含以下信息：</p><p>文件的访问模式（r/w/x）</p><p>文件所有者和组（owner/group）</p><p>文件大小</p><p>文件创建或状态改变的时间（ctime）</p><p>最近一次的读取时间（atime）</p><p>最近修改的时间（mtime）</p><p>定义文件特性的标志（flag）</p><p>文件真正内容指向的数据块（pointer）</p><p>另外，inode的特征有：</p><p>inode的数量和大小在磁盘格式化的时候就已经固定了，除非再次格式化重新设置，否则不可改变。</p><p>每个inode的大小均为128Bytes。</p><p>每个文件仅占用一个inode。</p><p>文件系统能够创建（存储）的文件数量和inode的数量有关，也和磁盘大小（数据块数量）有关。</p><p>系统读取文件时，需要先找到inode，分析inode记录的权限与用户是否符合，若符合才可以开始实际读取数据块中的内容。</p><p>为了解决inode数量可能不够用的问题，操作系统将inode记录block号的区域定义为12个直接、1个间接、1个双间接、1个三间接的记录区。</p><p>文件IO编程中常说的文件句柄，其实就是inode编号。<br />文件读取过程</p><p>已读取文件/var/log/message为例，讲解读取文件messages时，从磁盘中查找/读取文件内容的过程。</p><p>首先系统通过挂载信息（在超级块中，位置固定）找到根目录(/)的inode编号，根目录对应的inode是固定的（通常为2号）。</p><p>根据根目录的inode编号（2号），在inode table中找到对应的inode信息，从inode信息中找到存储根目录信息的目录块编号，根据编号找到数据块，如图中标记为‘/’的方格，该目录块存储的信息如图中的dentry所示。</p><p>从目录块中存储的信息中，找到文件名（目录名）为var所对应的inode编号（2667711）。</p><p>在inode table中找到编号为2667711的inode信息，从该inode信息中，找到var目录存放的数据块。从var数据块存储的信息中，找到log目录对应的inode编号（267850）。</p><p>重复上述步骤，直至找到message文件对应的inode结点，根据inode结点中记录的message文件内容对应的数据块，从数据块中读取内容。<br />扇区、块（簇/数据块）、页</p><p>在操作系统数据交互过程中，经常听到扇区、块（簇/数据块）、页这几种单位，他们在数据交互过程中的意义为：</p><p>扇区： 磁头从磁盘中读取数据的最小单位，即磁头每次从磁盘中读取数据，都是一个扇区一个扇区读的。</p><p>块（簇）： 操作系统与磁盘（硬盘）交互的最小数据单元（在linux系统中称为块，在windows系统中称为簇）。操作系统从硬盘中拿一块数据，即完成一次磁盘IO。块（数据块）的大小在硬盘格式化时被指定，一般有1K，2K，4K（最常用）。如果块的大小设置为4K，那么磁盘要读取8个扇区之后，才将数据块传给操作系统。另外，数据块也是DOS下数据存储的最小单元。例如，如果一个文件的大小为1K，而块的大小为4K，那么该文件还是会占用一个块，块中剩下的3K被空闲出来，不能用于存储其他数据。因此，设置块的大小时，需要考虑要存储文件的大小。</p><p>页： 操作系统访问内存时的最小单元，一般系统页的大小为4K（或者更大）。操作系统访问内存中的数据时，如果发现内存中没有哪个页可以提供该数据，那么会发生缺页，系统通过页替换（从硬盘中读取数据）的方式，将数据从硬盘读取到内存页中，再返回给调用者。</p><p>总的说来，主要就是不同系统、设备间数据交互时，使用了不同的机制和概念。其中磁盘内部（磁盘驱动程序从磁盘）读取数据时，以扇区为单位；操作系统从磁盘读取数据时，以块为单位；操作系统从内存读取数据时，以页为单位。<br />操作系统对文件存取操作的优化</p><p>并非每次读、写文件操作都会真正地从磁盘读出或写入，那样性能难以接受。为此操作系统使用了一系列机制，提升了文件IO的性能。<br />缓存</p><p>不管是硬盘还是操作系统，都会对从磁盘片中读取的数据进行缓存。硬盘中的缓存一般会比较小，如十几M，操作系统中的缓存则可能大很多。系统会将常用的文件数据放到主存储器的缓冲区，以加速文件系统的读写。一般情况下，只要系统的内存够用，系统会尽可能多的将磁盘中常用的文件缓存到内存中，直至内存耗尽（这是正常现象）。比如，如果你发现在电脑上读取文件的速度达到了2G每秒，那肯定不是真的从磁盘读取的，而是从缓存读取的。所以要测试磁盘真正的读数据的速度，需要先清空系统的缓存。<br />异步处理</p><p>当系统加载一个文件到内存后，如果该文件没有被改动过，则在内存区段的文件数据会被标记为clean，如果是被改动了，则会标记为dirty。此时所有的文件操作还是在内存中进行，并没有写入到磁盘中。系统会不定时的将内存中设置为dirty的数据写回到磁盘，以保持磁盘与内存数据的一致性。这个过程是异步的。你也可以sync命令，将内存中的数强制写回到硬盘。</p><p>另外，要注意的是，在正常关机的情况下，关机命令会主动调用sync来将内存中的数据写入到磁盘内，但是如果非正常关机（如断电、死机），由于数据没有来得及写入到磁盘，因此重新启动可能会花费很长的时间进行磁盘检验，甚至可能导致文件系统的损毁（非磁盘损坏）。<br />总结</p><p>本文读linux系统文件的读取过程从里到外做了较为详细的说明，已进入了linux操作系统层面，在下一篇文章中，可能会将这些原理与文件IO系统调用函数进行挂钩讲解，从而完成硬件-系统-应用的完整流程。</p>]]></description>
			<author><![CDATA[dummy@example.com (batsom)]]></author>
			<pubDate>Thu, 04 Aug 2022 14:55:18 +0000</pubDate>
			<guid>http://www.gentoo-zh.org/viewtopic.php?pid=27#p27</guid>
		</item>
	</channel>
</rss>
