文件如何在低级别复制?

Las*_*son 3 hardware winapi low-level file-copying

我有一个小问题:

例如,我正在使用.NET Framework中的System.IO.File.Copy()方法.此方法是WinAPI的CopyFile()函数的托管包装器.但CopyFile函数如何工作?它与HDD的固件交互,或者可能通过Assembler或其他一些其他操作执行其他操作......

从最高级别到最低级别看起来如何?

Wil*_*ung 9

最好从底部开始,逐步提升.

磁盘驱动器在最低级别组织为扇区,轨道和磁头的集合.扇区是轨道的一部分,轨道是磁盘本身的区域,由磁头在其下方旋转的磁头位置表示,磁头是从磁盘读取数据的实际元素.

由于轨道是根据磁头距离磁盘中心的距离来测量的,因此您可以看到磁道中心的"长度"如何短于磁盘外缘的磁道长度.

扇区是轨道的片段,通常具有固定长度.因此,内部轨道将比外部轨道保持更少的扇区.

现在,大多数磁盘几何都由驱动器控制器本身处理,但在过去,该组织由操作系统和磁盘驱动程序直接管理.

驱动电子设备和磁盘驱动器协作以尝试将磁盘表示为顺序系列的固定长度块.

因此,您可以看到,如果您有一个10MB的驱动器,并且您使用512字节的磁盘块,那么该驱动器将具有20,480"块"的容量.

这个块组织是构建其他所有东西的基础.获得此功能后,您可以通过磁盘驱动程序和驱动器控制器告知磁盘转到磁盘上的特定块,并使用新数据读/写该块.

文件系统将这个块堆组织到它自己的结构中.FS必须跟踪正在使用的块以及哪些文件.

大多数文件系统都有一个固定的位置"它们从哪里开始",也就是说,一些地方在启动时可以尝试查找有关磁盘布局的信息.

考虑一个没有目录的原始文件系统,支持具有8个字母名称和3个字母扩展名的文件,加上1个字节的状态信息,以及2个字节用于文件在磁盘上启动的块编号.我们还可以假设系统有1024个文件的硬限制.最后,它必须知道磁盘上正在使用哪些块.为此,它将使用每块1位.

此信息通常称为"文件系统元数据".当磁盘被"格式化"时,现在只需要编写新的文件系统元数据.在过去,实际上是在空白磁介质上写入扇区标记和其他信息(通常称为"低级格式").今天,大多数驱动器已经采用低级格式.

对于我们的原始示例,我们必须为目录分配空间,并为"目录"分配空间,该数据说明正在使用哪些块.

我们还要说文件系统必须从块16开始,这样OS就可以使用前16个块,例如"引导扇区".

因此,在块16,我们需要存储14个字节(每个文件条目)*1024(文件数)= 12K.除以512(块大小)为24块.对于我们的10MB驱动器,它有20,480个块.20,480/8(8位/字节)是2,560字节/ 512 = 5块.

在磁盘上可用的20,480个块中,文件系统元数据是29个块.在操作系统中添加16个,在20,480个中有45个区块,剩下20,435个"免费区块".

最后,每个数据块保留最后2个字节以指向文件中的下一个块.

现在,要读取文件,请在目录块中查找文件名.从那里,您可以找到文件第一个数据块的偏移量.你读了那个数据块,抓住最后两个字节.如果这两个字节是00 00,那么这就是文件的结尾.否则,取出该数字,加载该数据块,并继续运行直到读取整个文件.

文件系统代码在末尾隐藏指针的细节,并简单地将块加载到内存中,供程序使用.如果程序执行读取(缓冲区,10000),您可以看到它将如何转换为从磁盘读取几个数据块,直到填充缓冲区或达到文件结尾.

要写入文件,系统必须首先在目录中找到可用空间.一旦有了,它就会在TOC位图中找到一个空闲块.最后,它获取数据,写入目录条目,将其第一个块设置为位图中的可用块,切换位图上的位,然后获取数据并将其写入正确的块.系统将缓冲这些信息,以便理想情况下只需要在块满时写入块.

在写入块时,它会继续消耗来自TOC的位,并在块运行时将块链接在一起.

除此之外,"文件复制"是一个简单的过程,从系统利用文件系统代码和磁盘驱动程序.文件复制只是读入一个缓冲区,填充它,写出缓冲区.

文件系统必须维护所有元数据,跟踪您从文件中读取的位置或您正在编写的位置.例如,如果从文件中只读取100个字节,显然系统将需要读取整个512字节数据块,然后"知道"它在字节101上,当您尝试从文件中读取另外100个字节时.

另外,我希望很明显,这是一个非常粗糙的文件系统布局,存在很多问题.

但基本原理在那里,并且所有文件系统都以某种方式工作,但细节差别很大(大多数现代文件系统不再有硬限制,作为一个简单的例子).


mor*_*itz 5

这是一个问题要求或一个非常长的答案,但我正在努力使其简短.

基本上,.NET Framework包含一些"本机"调用,这些调用是在较低级别库中处理的.这些较低级别的调用通常包含在缓冲区逻辑中,以隐藏复杂的内容,例如同步文件内容.

下面是本机级别,与OS内核交互.内核是任何操作系统的核心,然后将您的高级指令转换为您的硬件可以理解的内容.例如,Windows和Linux都使用硬件抽象层,这是一个隐藏通用接口背后的硬件特定细节的系统.因此,为特定设备编写驱动程序只是实现某些设备必须提供的所有方法的任务.

在你的硬件上调用任何东西之前,文件系统都会被涉及,文件系统本身也会缓冲和缓存很多,但是再次透明,所以你甚至都没有注意到.呼叫队列中的最后一个元素是设备本身,同样,大多数设备符合某些标准(如SATA或IDE),因此可以以类似的方式进行接口.

我希望这有帮助 :-)