一些文件复制程序喜欢rsync
并且curl
能够恢复失败的传输/复制。
请注意,这些失败的原因可能有很多,在某些情况下,程序可以进行“清理”,而在某些情况下则不能。
当这些程序恢复时,它们似乎只是计算成功传输的文件/数据的大小,然后开始从源读取下一个字节并附加到文件片段。
例如,“制作”到目的地的文件片段的大小是 1378 字节,因此它们只是从原始文件的第 1379 字节开始读取并添加到片段中。
我的问题是,知道字节由位组成,并且并非所有文件都将其数据分段为干净的字节大小的块,这些程序如何知道他们选择开始添加数据的点是正确的?
当写入目标文件时,会发生类似于 SQL 数据库的某种缓冲或“事务”,无论是在程序、内核还是文件系统级别,以确保只有干净、格式良好的字节才能到达底层块设备?
或者程序是否假设最新的字节可能不完整,所以他们在假设它坏的情况下删除它,重新复制字节并从那里开始附加?
知道并非所有数据都表示为字节,这些猜测似乎不正确。
当这些程序“恢复”时,他们怎么知道他们是从正确的地方开始的?
LSe*_*rni 41
为了清楚起见 - 真正的机制更加复杂以提供更好的安全性 - 您可以想象这样的写入磁盘操作:
如果进程在 (1) 处中断,则磁盘上没有任何内容,文件完好无损并在前一个块处被截断。您发送了 5000 个字节,磁盘上只有 4096 个字节,您在偏移量 4096 处重新启动传输。
如果在 (2) 处,除了内存之外什么都不会发生。与 (1) 相同。如果在 (3) 处,数据被写入但没有人记得它。你发送了 9000 字节,4096 被写入,4096 被写入并丢失,其余的只是丢失。传输在偏移量 4096 处恢复。
如果在 (4),数据现在应该已经提交到磁盘上。流中的下一个字节可能会丢失。您发送了 9000 个字节,写入了 8192 个,其余的丢失了,传输在偏移量 8192 处恢复。
这是一个简化的过程。例如,阶段 3-4 中的每个“逻辑”写入不是“原子”,而是产生另一个序列(让我们将其编号为 #5),其中将块细分为适合目标设备(例如硬盘)的子块) 发送到设备的主机控制器,它也有缓存机制,最后存储在磁盘上。这个子序列并不总是完全在系统的控制之下,因此将数据发送到硬盘并不能保证它已经被实际写入并且可以读回。
几个文件系统实现了日志,以确保最易受攻击的点 (4)实际上并不脆弱,通过写入元数据,您猜对了,无论在阶段 (5) 中发生什么,事务都将始终如一地工作。
如果系统在事务中间被重置,它可以恢复到最近的完整检查点。写入的数据仍然丢失,与情况(1)相同,但恢复会解决这个问题。实际上不会丢失任何信息。
Kus*_*nda 10
注意:我没有查看rsync
任何其他文件传输实用程序的来源。
编写一个 C 程序来跳转文件末尾并以字节为单位获取该位置的位置是微不足道的。
这两个操作都是通过对标准 C 库函数的一次调用完成的lseek()
(lseek(fd, 0, SEEK_END)
返回为文件描述符打开的文件的长度fd
,以字节为单位)。
一旦对目标文件完成此操作,就lseek()
可以对源文件执行类似的调用以跳转到适当的位置:lseek(fd, pos, SEEK_SET)
. 假设源文件的较早部分已被标识为未更改(不同的实用程序可能以不同的方式执行此操作),则可以在该点继续传输。
磁盘上的文件可能会碎片化,但文件系统将确保应用程序将文件视为字节的顺序序列。
关于位和字节的评论中的讨论:可以写入磁盘的最小数据单位是byte。单个字节至少需要在磁盘上分配一个数据块。块的大小取决于文件系统的类型,也可能取决于管理员在初始化文件系统时使用的参数,但通常介于 512 字节和 4 KiB 之间。写操作可能由内核、底层 C 库或应用程序本身缓冲,作为优化,实际写入磁盘可能以适当块大小的倍数发生。
不可能将单个位写入文件,如果写入操作失败,则不会在文件中留下“半写入字节”。
这基本上是两个问题,因为像 curl 和 rsync 这样的程序非常不同。
对于像 curl 这样的 HTTP 客户端,它们会检查当前文件的大小,然后Content-Range
随请求发送标头。服务器要么使用状态代码206
(部分内容)而不是200
(成功)继续发送文件的范围并继续下载,要么忽略标头并从头开始并且 HTTP 客户端别无选择,只能重新下载所有内容再次。
此外,服务器可能会或可能不会发送Content-Length
标头。您可能已经注意到,某些下载没有显示百分比和文件大小。这些是服务器不告诉客户端长度的下载,因此客户端只知道它下载的数量,而不知道接下来会有多少字节。
使用Content-Range
带有开始和的标题某些下载管理器使用停止位置一次从不同来源下载文件,如果每个镜像本身比您的网络连接慢,则可以加快传输速度。
另一方面,rsync 是一种用于增量文件传输的高级协议。它在服务器端和客户端生成文件部分的校验和,以检测哪些字节是相同的。然后它只发送差异。这意味着它不仅可以恢复下载,而且如果您在非常大的文件中间更改了几个字节而无需重新下载文件,它甚至可以下载更改的字节。
另一个用于恢复传输的协议是 bittorrent,其中.torrent
文件包含文件中块的校验和列表,因此可以以任意顺序从不同来源并行下载和验证块。
请注意, rsync 和 bittorent 将验证磁盘上的部分数据,而恢复 HTTP 下载则不会。因此,如果您怀疑部分数据已损坏,则需要检查完整性,即使用最终文件的校验和。但只是中断下载或丢失网络连接通常不会损坏部分文件,而在传输过程中电源故障可能会损坏。
归档时间: |
|
查看次数: |
5032 次 |
最近记录: |