虚位以待(AD)
虚位以待(AD)
首页 > 操作系统 > Windows系列 > 计算机文件读写原理

计算机文件读写原理
类别:Windows系列   作者:码皇   来源:<a href="http://blog.csdn.net/ozhuzhiyuan" target="_blank" rel="nofollow   点击:

计算机文件读写原理。前言。在一个txt文件中,修改其中一个字,然后保存,这期间计算机内部到底发生了什么?操作系统如何将键盘输入的字符通过主板上密密麻麻的总线和芯片送到磁盘上的盘片上的? 这其中涉及的所有环节,就算用一本书也不一定能完全说明。

计算机文件读写原理

前言

在一个txt文件中,修改其中一个字,然后保存,这期间计算机内部到底发生了什么?操作系统如何将键盘输入的字符通过主板上密密麻麻的总线和芯片送到磁盘上的盘片上的? 这其中涉及的所有环节,就算用一本书也不一定能完全说明。然而我想首先从宏观上认知整个过程,再逐步的去细化。因此,本篇文章的目的是从一从一个非常抽象的层次、一个非常局限的角度来分析文件读写的原理。

为什么说局限

为什么说是局限的角度呢,因为文件IO整个生命流程涉及到的环节太多了,每个环节还有很多不同的实现模式,因此我尝试着每个环节只考虑一种情况,从而能认知整个流程。

文件操作分为读和写,写可以分为覆盖写和追加写;写操作可以使用操作系统缓存cache,也可以bypass操作系统cache;写IO可以分为Write Through(透写)和Write Back(回写);另外文件数据可以存放在本地,也可以存放在外置存储中;存放在本地也分有无raid卡;硬盘也分传统硬盘或SSD,SAS或SATA接口,甚至nvme,等等。如果这些都考虑,很难说清楚文件读写的原理,我认为首先弄明白其中一种情况下的原理,再运用联系思维考虑其他情况,更有效率。

下文我将以Linux系统为例,阐述IO覆盖写,使用Write Back模式,使用操作系统缓存cache,底层使用传统SAS磁盘情况下的写IO流程。

写IO

为了便于理解,下图我将文件写IO涉及到的重要硬件设备和软件逻辑结构表示在一张图中,大致上左边是硬件,右边是软件逻辑结构,以下以应用程序覆盖写文件A为例

 

这里写图片描述

 

应用程序需要修改文件A中的部分字段,首先应用程序将待写数据存放在其user buffer结构中,user buffer 通过MMU 映射,数据实际存放在物理内存中。现在应用程序需要将待写数据写入硬盘。

①程序进程调用内核函数write(),将待写文件标识(句柄)、待写数据相对文件首部的字节偏移量(offset xx)、待写数据长度(2KB)和待写数据的位置一并传给内核 ;

注:在程序打开文件时,内核在PageCache中创建一个虚拟的文件A’,这个文件A’从文件系统inode结构(下文讲)中映射出来,由若干个page组成,初始情况下文件A’存在与逻辑地址空间内,不占用物理内存。文件A’的逻辑长度参考文件实际长度占用page的整数倍,这里假设page 大小为4KB。

②如图,内核根据文件字节偏移量和上文提到的虚拟文件A’计算出待写数据占用的page1;(这里面待写数据只有2KB,小于page大小,因此待写数据落入page1中)

③计算出page号后,内核尝试找到page1对应的物理地址,以进行下一步操作。此时发现page1对应的数据并没有调入内存中,产生缺页,此时需要内核将page1对应的数据完整的从磁盘调入内存;(注意:此处和内存换页没有关系,这里可以看到使用操作系统Pagecache的写IO可能会产生IO读惩罚)

注:文件系统的主要功能就是组织文件在磁盘上的分布,文件是连续的结构,但其在磁盘上却是离散分布的。文件系统将磁盘格式化成若干个块,每个块由若干个连续物理扇区组成,这个真实存在的块叫做物理块。为了提高利用率,同一个文件映射出的物理块可能在磁盘的任何位置,不一定是连续的。因此文件系统需要一个链表来记录文件对应的物理块位置,这个结构在linux中就是inode

④文件系统将page号映射到对应的块,然后根据inode可查到文件块对应的真实物理地址LBA,内核将请求封装后转给设备驱动层。

⑤设备驱动将请求翻译成若干各个SCSI指令,驱动SAS控制器通过SAS总线向磁盘发送指令:

SCSI Read() LBA0x****** Len=N N=读取字节大小/扇区大小

注:上述过程主要发生在CPU与内存之间,CPU从内存中读出指令并执行,最后CPU将指令通过PCIe总线发送给了SAS控制器,SAS控制器将指令发送到SAS总线上

⑥磁盘收到SCSI指令后,找到LBA对应的实际盘面和柱面,读出对应的扇区,发回SAS控制器;

⑦从磁盘读出的数据(这里是4KB大小)从原路返回,最后写入到page1对应的物理内存中;

⑧内核用代写2KB数据替换掉Page1对应的2KB待替换数据;

⑨此时内核向程序进程反馈:写入成功;

⑩内核在合适时机将内存中的脏页刷入磁盘。

⑨⑩两步表示 Write Back模式,内核在没有将数据写入磁盘时就返回写入成功,以提高效率,相当于内核“欺骗”了应用程序。实际上不光内核会这样做,底层的很多环节也会有这样的情况,比如磁盘也会“欺骗”SAS控制器。如果此时发生系统掉电,所有易失性存储中的数据全部丢失,并未写入磁盘,而应用程序认为写IO已经完成了,下次开机时就会产生数据不一致。程序可以设置Write Through 模式,此时内核会等底层层层上报写入成功后,才会反馈写入成功。

小结

为了能完整的表述整个IO过程,这其中我简化掉了很多流程。比如这里面没有提卷管理层,还有一个IO中很重要的概念——队列(queue),只要有IO瓶颈,就会有队列,操作系统中有多处队列,比如Linux中io scheduler。磁盘上也有队列,以实现NCQ等算法。

相关热词搜索: