创建启动U盘时使用的sync命令有啥用处?

debian的手册中提到,在创建启动U盘时,使用的命令中有sync,如下:

cp debian.iso /dev/sdx
sync

上面的sync命令有什么用处?

我大概知道的是,sync是把内存中的数据同步到硬盘。有可能cp命令执行完毕后,iso文件数据并没有全部完成传输,未完成的部分仍然在后台继续向U盘传输,只不过屏幕上显示已经完成。

但这好像有点矛盾。

U盘这类的东西,很多时候就是要“拿下来”,即文件拷贝完成后就从电脑上拨下来。如果没有使用sync命令而直接拨下来,大概率会损坏其中的数据,这有点“不人文”。

我试过拷贝文件到ssd硬盘,也有同样的现象,就是拷贝速度远大于正常速度,拷贝完成后执行sync命令,命令会执行较长一段时间后才返回$提示符。

我的问题是:

  1. 这是啥原理?(拷贝工作已经完成,还要sync一下)
  2. 有没有什么方法能够让拷贝文件完成后不需要执行sync命令?即拷贝完成就是真的完成。
  3. sync命令在这种场景中是不明有点多余,它让用户的操作变复杂了。windows是不是完全不用考虑这个问题?
  1. 缓存呗。为了性能。
  2. 程序可以调用 fsync 系统调用来等待操作完成。cp 不支持,dd 可以加 conv=fsync 参数。
  3. Windows 的情况我不清楚。我记得改过。

但是直接写盘的块文件是个很少见的操作。

对于文件系统的话,挂载时加上 sync 选项即可。使用 udev 规则,可以让 udisks 挂载时自动给特定的设备(如 USB 设备)应用特定的选项。

但我不喜欢这样,性能差、磨损高。不如我拔之前先卸载文件系统。

我大概理解了,启动U盘创建时使用的sync命令其实很少用到。

看楼主热心,我也跟着学习了。
终端输入sync看帮助,说,有同步数据元数据的作用。在操作里作用是必须。

sync是告诉系统立刻把各种缓存写入,这很重要,特别是跨盘读写,最常用的就是往U盘放大文件,有时候你会看到进度条一下就跑完了,你以为移动完了,实际上只是放到了缓存而已,写入并未完成。如果你拔出upan,只会得到一个损坏的文件。我发现很多发行版都有这毛病,包括kde,dde,gnome没用过,不知道情况怎么样。这点微软做的很好。

1 个赞

我在整理debian的新手教程,教程中对于新手能够理解的部分,我尽量尝试给整理出来,这次正好是整理启动U盘创建这一部分内容,涉及到sync命令的作用/意义。

至于为什么Linux系统需要sync命令,我暂时的推测是,Linux还没有完全摆脱server os的身份。

楼上提到ms做得好,我其实没有觉得“好”或“不好”,而是觉得二者只是侧重方向不同(但不得劲儿的感觉是真的):Linux侧重方向主要还是server,而windows主要方向是pc,而且是很多年的pc。换句话说,用server来和pc进行比较,有点说不通。

这样推测的理由主要是,摆脱u盘的sync命令(像windows一样)在技术实现上应该很容易,只不过关心的人相对比较少而已。而之所以关心的人少,是因为少有人从pc的角度考虑Linux。

有一个问题我想再确认一下,就是你提到的性能。

通过缓存来提高性能,我的理解是,应该只是“看着”性能好,因为只是看起来传输过程结束了,但事实是看不见的后台并没有结束,仍然在传输数据。

如果是这样的话,那么这种性能提高,其实并不是真正的性能提高?
或者,换个说法,这样的性能提高,在哪些应用/地方有实际的意义?

如果反复写入的话,相邻位置的数据可以合并在一起写入,对同一位置的多次写入只需要写最后一次的数据(注意这里的数据包括文件元数据、目录等)。所以是否能有实际的性能提升,取决于写入的模式。如果只是复制大文件然后拔盘的话,确实没有任何提升。

1 个赞

我觉得,各个命令已经打包,完全可以使用源码编译含有那命令的功能而不用那个命令,只是,这不是多做什么事,浪费已经有的命令了?

相比之下,我感觉从udev角度来处理,比从源码角度处理要更适合一些。

当然可以不 sync,只要你正常卸载 U 盘(比如通过各种桌面系统的卸载菜单或者 umount 命令)就可以。操作系统会正确的写回缓存。

就我所知用 sync 的唯一原因可能是你的系统挂掉了没法正常关机,或者要做什么文件系统的 hack,不得不强制系统 sync 然后强制断电。正常用户应该没有任何使用 sync 命令的必要。当然,如果我的认知有错误,欢迎指出来 :slight_smile:


编辑:重新看了下手册的细节,

4.3. 为从 U 盘引导准备文件

针对此架构的 Debian安装映像是采用 isohybrid 技术创建的,这意味着它们可以被直接写入 U 盘,这是非常简单的制作安装介质的方法。只需为 U 盘选择一个大小合适的映像(如 netint、CD 或 DVD-1)。参阅 第 4.1 节 “官方的 Debian GNU/Linux 安装映像” 获取安装映像。

您选中的安装映像应该被直接写入 U 盘,覆盖它当前的内容。例如,使用已有的 GNU/Linux 系统,映像文件可以参照下面方法写入 U 盘,写之前请确认 U 盘已经卸载: ”

cp debian.iso /dev/sdX
sync

对大多数用户来说,简单地把安装映像写入 U 盘已经够用。如果您有特殊需求,请阅读此[维基页面]。

原来是绕过了文件系统直接向块设备写入,那么这样就没有“卸载 U 盘”一说了。虽然操作系统会在后台写入缓存,但是用户显然观察不到这个过程。使用 sync 命令阻塞地等待缓存写入是最有效的手段。

我的观点是,恰恰相反,Linux 可以暴露块设备的细节让用户能用 cp 命令直接操作裸设备,是用户选择绕过了减速带(操作系统保护)直奔终点,而 Windows 没有提供类似的机制。

对于 Windows 用户,简单的使用命令行就能卸载文件系统直接操作块设备显然是几乎不可能的(大概率需要用 win32api 或者最新的 winrt,我并不了解 Windows 软件开发),往往需要使用第三方软件。
例如,我最常用的是 Rufus和 Ventoy,这两者都提供了良好的用户操作体验,这些软件都包含了 sync 对应的逻辑,只是用户观察不到。

Linux 当然也有很多类似的工具用于从 ISO 创建启动盘,例如 balenaEtcher(似乎无法创建 windows 启动盘)以及 Ventoy,,使用这些软件同样不需要手动 sync。但是简单的使用 cp 命令也不失为一种选择,只是用户需要知道自己在做什么,并且在写入完成后才能移除设备,或者使用 sync 命令等待写入结束

如前文所述,debian 安装手册里提到的 sync 只是一种特殊情况下的特殊用法。

所有操作系统都是这样做的,微软的 windows 也是需要正确卸载 U 盘后才能移除的。实际上两者的写入速度不会有什么差异,耗时都是取决于 U 盘写入速度。

有时候你会看到进度条一下就跑完了

从使用经验看 windows 似乎不会对 U 盘设备使用太大的缓存。

  1. 合并 I/O 操作,最大程度的填满硬件队列,提高吞吐量(例如 NVMe 最大支持 64K 的队列数量和单队列 64K 深度[来源请求])
  2. 合并小尺寸写入,对于闪存这种固定写入大小,写入前必须擦除固定大小的设备可以节约寿命,降低主控算法负担
  3. 顺序写入,提高设备性能,如机械硬盘寻道时间很长,特别的叠瓦式机械硬盘的随机性能更差,合并写入可以给操作系统充分的优化空间,更好的实现顺序写入。

操作系统通过缓存 I/O 操作一方面能充分利用内存降低运行 I/O 操作的程序的系统调用延迟,另一方面通过缓存扩宽了操作空间,就能有更多的信息来优化 I/O 性能。

但是任何优化都是有假设和前提的,大文件顺序写入这种操作刚好满足了以上全部假设,所以操作系统的优化才显得没有作用。但是总的来说,缓存操作是有利于系统整体性能的。

突然想到这个话题,挖个坟。

Windows 定义了两个main策略,即“快速删除”和“提高性能”,用于控制系统与外部存储设备(如 USB 拇指驱动器或已启用 Thunderbolt 的外部驱动器)的交互方式。 从 Windows 10 版本 1809 开始,默认策略为“快速删除”。 在早期版本的 Windows 中,默认策略为 “提高性能”。

可以更改每个外部设备的策略设置,如果断开设备连接,然后将其再次连接到同一计算机端口,则设置的策略将保持有效。

更多信息
可以使用存储设备策略设置来更改 Windows 管理存储设备的方式,以更好地满足你的需求。 策略设置具有以下效果:

快速删除:此策略以保持设备随时可供删除的方式管理存储操作。 无需使用安全删除硬件过程即可删除设备。 但是,为此,Windows 无法缓存磁盘写入操作。 这可能会降低系统性能。
更好的性能:此策略以提高系统性能的方式管理存储操作。 此策略生效后,Windows 可以将写入操作缓存到外部设备。 但是,必须使用“安全删除硬件”过程来删除外部驱动器。 安全删除硬件过程可确保所有缓存操作完成,从而保护设备上的数据完整性。

简而言之最新版的 Windows 对于可移动存储设备的默认策略改为了“快速删除”,因此不需要担心缓存行为造成的删除设备等待时间过长的问题了。当然,你也可以改回旧行为。

另外根据观察,至少 Debian 12 的 KDE Plasma 对于挂载的可移动存储设备写入策略是“更好的性能”,系统会积极利用内存进行缓存,合并写入。