低层级下如何复制文件?

3

我有一个小问题:

例如,我正在使用来自.NET Framework的System.IO.File.Copy()方法。这个方法是CopyFile()函数的托管包装器,它来自WinAPI。但是CopyFile函数是如何工作的?它与HDD的固件进行交互,还是通过汇编语言执行其他操作,或者可能是其他某些方式...

从最高层次到最低层次,它是什么样子的呢?

3个回答

10
最好从底部开始,逐步向上构建。
磁盘驱动器在最底层被组织为一个扇区、磁道和磁头的集合。扇区是磁道的一部分,磁道是磁盘本身的区域,由盘片在磁头下旋转时的位置表示,而磁头则是从盘片中读取数据的实际元素。
由于磁道是基于磁头距离磁盘中心的距离测量的,因此您可以看到磁盘中心越靠近,磁道的“长度”就比磁盘外缘的磁道短。
扇区是磁道的一部分,通常具有固定长度。因此,内圈的磁道将比外圈的磁道容纳更少的扇区。
如今,大部分的磁盘几何结构都由驱动控制器自行处理,尽管过去这种组织是通过操作系统和磁盘驱动程序直接管理的。
驱动电子设备和磁盘驱动程序协作,试图将磁盘表示为一系列顺序的固定长度块。
因此,您可以看到,如果您有一个10MB的驱动器,并且您使用512字节的磁盘块,则该驱动器的容量将为20,480个“块”。
此块组织是建立其他所有内容的基础。一旦您拥有此功能,就可以通过磁盘驱动程序和驱动控制器告诉磁盘去访问磁盘上的特定块,并读取/写入新数据。
文件系统将这堆块组织成自己的结构。文件系统必须跟踪正在使用哪些块以及哪些文件在使用它们。
大多数文件系统都有一个固定的起始位置,即,它们可以在启动时前往查找有关磁盘布局的信息的某个位置。
考虑一个简陋的没有目录支持的文件系统,支持具有8个字母名称和3个字母扩展名的文件,以及1个字节的状态信息和2个字节的块号,其中文件开始存储在磁盘上。我们还可以假设该系统最多只能存储1024个文件。最后,它必须知道磁盘上正在使用的块。为此,它将每个块使用1位。

这些信息通常称为“文件系统元数据”。 当磁盘被“格式化”时,现在只需要写入新的文件系统元数据即可。 在旧时代,实际上需要在空白磁介质上写入扇区标记和其他信息(通常称为“低级格式化”)。 如今,大多数驱动器已经具备低级格式。

对于我们简单的示例,我们必须为目录分配空间以及为“目录表”分配空间,它包含了哪些块正在使用的数据。

我们还将说文件系统必须从块16开始,以便操作系统可以使用前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,则表示已经到达文件末尾。 否则,取该数字,加载该数据块,并继续进行,直到整个文件被读取。

文件系统代码隐藏了末尾指针的详细信息,只是将块加载到内存中供程序使用。 如果程序执行read(buffer, 10000),则可以看到它将转换为从磁盘中读取几个数据块,直到填满缓冲区或到达文件末尾。

要写入文件,系统首先必须在目录中找到可用空间。一旦找到,它就会在TOC位图中找到一个可用块。最后,它会获取数据,写入目录条目,将其第一个块设置为来自位图的可用块,切换位图上的位,并将数据写入正确的块。系统将缓冲此信息,以便最理想的情况下只需在块满时写入一次。
在写入块的同时,它继续从TOC中使用位,并随着进程将块链接在一起。
除此之外,“文件复制”是一个简单的过程,可以利用文件系统代码和磁盘驱动。文件复制只需读入缓冲区,填充它,然后将它写出即可。
文件系统必须维护所有元数据,并跟踪您正在从文件中读取或写入的位置。例如,如果您只从文件中读取100个字节,显然系统需要读取整个512字节的数据块,然后“知道”在您尝试从文件中再读取另外100个字节时,它在第101个字节上。
此外,希望显而易见的是,这是一个非常简陋的文件系统布局,并存在许多问题。
但基本要素都在那里,所有文件系统都以某种类似于此的方式工作,但细节差异很大(例如,大多数现代文件系统不再具有硬限制)。

5
这可能是一个需要回答很长的问题,但我尝试简要概括一下。
基本上,.NET Framework包装了一些“本地”的调用,这些调用在低级库中被处理。这些低级别的调用通常会被包装在缓冲逻辑中,以隐藏像同步文件内容这样复杂的东西。
下面是与操作系统内核交互的本机级别。内核是任何操作系统的核心,然后将您的高级指令转换为硬件可以理解的内容。例如,Windows和Linux都使用硬件抽象层,这是一个将硬件特定细节隐藏在通用接口后面的系统。编写特定设备的驱动程序只需要实现某个设备提供的所有方法即可。
在任何东西调用您的硬件之前,文件系统都参与其中,而文件系统本身也会进行大量缓冲和缓存,但是再次透明,因此您甚至不会注意到。调用队列中的最后一个元素是设备本身,大多数设备符合某些标准(如SATA或IDE),因此可以以类似的方式进行接口化。
希望这有所帮助 :-)

2
.NET框架调用Windows API。
Windows API具有管理各种文件系统中文件的功能。
然后就取决于所涉及的文件系统。请记住,它不一定是HDD上的“正常”文件系统;它甚至可以是一个外壳扩展程序,只是模拟驱动器并将数据存储在您的gmail帐户中,或者其他什么地方。关键是使用Windows API中相同的文件操作函数作为对许多可能的较低层数据的抽象。
因此,答案实际上取决于您感兴趣的文件系统类型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接