Linux 下复制数据到 U 盘切记先正常弹出或卸载后再拔出

一、内容提要

使用过 Linux 的朋友可能会发现一个现象,那就是在 Linux 下有时往 U 盘里复制数据,不论是图形界面还是命令行下,貌似是极速的复制完成。不过,如果点击弹出U盘或 umount 卸载 U 盘,却会报告正有数据写入U盘,无法弹出或卸载。这时,如果强行拔出U盘,复制数据就会失败。而在 Windows 下面,基本上复制完毕点击弹出就可以弹出U盘。为什么会出现这种现象?如何在 Linux 下面正确的使用 U 盘?下面我以 VirtualBox 中的 Ubuntu 22.04 Linux 虚拟机为例,挂载一块实际的 4G 老U盘的 FAT32 和 NTFS 分区为例,在图形界面和命令行下演示一下具体的表现,并简要解释一下其中的原因和怎样让 U 盘复制数据的表现变得和 Windows 类似。视频演示地址:【Linux 下复制数据到 U 盘切记先正常弹出或卸载后再拔出】 https://www.bilibili.com/video/BV1Ta4y1B7X2/?share_source=copy_web&vd_source=d1925b070926f23b2b6676137251e9ea

二、Ubuntu 22.04 下面 U 盘 写入数据的具体表现

经过实际测试,在 Ubuntu 22.04 默认的 Nautilus 文件管理器中,默认的设置是可以自动挂载插入的 U 盘分区的(参见参考链接1)。这时,在文件管理器中往 U 盘的 FAT32 分区中复制数据,其表现与 Windows 的默认配置类似,复制结束后点击弹出U盘就可以顺利弹出。但是,如果是 NTFS 分区,在 Ubuntu 下会显示很快的复制完成,点击弹出却被告知,有数据正在写入,无法弹出。命令行下使用 cp 命令复制数据的表现也与图形界面的表现一致。

三、Linux 下 flush 和 sync 挂载参数

那么,为什么在 Windows 下 U 盘数据复制完成后就可以立即弹出呢?而 Linux 下不同的分区格式又有如上不同的表现呢?归结到底的原因是 U 盘磁盘数据写入的策略不同。
Windows 的写入策略我这里就不展开了(参见参考链接2), 这里详细解释一下 Linux 下的写入缓存策略是如何影响不同分区格式的写入表现的。
通过在命令行下执行 mount 命令查看如下:

/dev/sdb1 on /media/mdx/FAT32PART type vfat (rw,nosuid,nodev,relatime,uid=1000,gid=1000,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,showexec,utf8,flush,errors=remount-ro,uhelper=udisks2)

可以查看到 FAT32 格式的分区的挂载选项里有个 flush 选项,查看 man mount,其解释是:

flush If set, the filesystem will try to flush to disk more early than normal. Not set by default.

man mount


大概意思是比通常的策略更早一些写入物理磁盘。

对于 NTFS 格式分区在文件管理器里的自动挂载后的选项,使用 mount 命令查看如下:

/dev/sdb2 on /media/mdx/NTFSPART type ntfs3 (rw,nosuid,nodev,relatime,uid=1000,gid=1000,iocharset=utf8,windows_names,uhelper=udisks2)

其中没有看到相关的同步写入磁盘选项。

手工卸载 NTFS 分区再加上一个 sync 挂载选项后,再复制数据进入相应分区就可以同步写入物理磁盘了。

udisksctl mount -t ntfs3 -o sync -b /dev/sdb2

(Udisks2 用 udiskctl 命令挂载磁盘分区参见文末参考链接3

或者:

sudo mount -t ntfs3 -o sync /dev/sdb2 /mnt -v

所以,控制能否同步写入物理磁盘的策略是由自动挂载的选项决定的。
另外,使用 sync 挂载选项可能对 U盘的使用寿命有一定的负面影响,参见 man mount 相关内容:

sync All I/O to the filesystem should be done synchronously. In the case of media with a limited number of write cycles (e.g. some flash drives), sync may cause life-cycle shortening.

man mount

四、更改 U 盘写入缓存的策略
这里讲一下在 Ubuntu 22.04 下面怎么修改文件管理器的自动挂载选项。这里的方法适用于 Udisks2 2.9 及以上的版本,如 Ubuntu 22.04 及 Fedora 36 等发行版。(参见参考链接4

1、方法一,修改 Udisks2 的默认挂载选项配置文件:/etc/udisks2/mount_options.conf

# /etc/udisks2/mount_options.conf
[defaults]
exfat_defaults=uid=$UID,gid=$GID,iocharset=utf8,errors=remount-ro,sync
ntfs_defaults=uid=$UID,gid=$GID,windows_names,sync

这里在 EXFAT 和 NTFS 分区的 Udisks2 默认挂载选项中均加了 sync。注意,这里并不区分是 USB 设备还是其他存储设备。

2、方法二,修改 Udisks2 自动挂载的 Udev 规则:

SUBSYSTEM!="block", GOTO="udisks_mount_options_end"
ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="udisks_mount_options_end"
ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="?*", GOTO="udisks_mount_options_end"
SUBSYSTEMS=="usb", ENV{ID_FS_TYPE}=="ntfs|exfat", ENV{UDISKS_MOUNT_OPTIONS_DEFAULTS}="sync"
LABEL="udisks_mount_options_end"

相比UDisks2的默认挂载选项设置,在 Udev 规则中设置 Udisks2 的默认挂载选项更灵活一些,比如上面可以指定仅更改 usb 设备的默认挂载规则。

五、未尽事宜

1、对于 Deepin 20.9 和 Ubuntu 20.04 等系统的 Udisks2 2.8 及以下的版本,我暂时没有发现直接更改默认挂载选项的办法。可能禁止 Udisks2 自动挂载,使用 Udev 规则自定义挂载动作可以办到。另外,网上也有从源码安装 Udisks2 新版的方法来解决这个问题(见下参考链接5)。

2、NTFS格式的分区挂载选项加上 sync 参数后,Ubuntu22.04 命令行用 cp 复制数据到 U 盘的速度还不到图形界面 nautilus 文件管理器复制速度的一半。应该与 cp 命令复制文件使用的数据块大小有关,使用 dd 命令复制指定了 bs=1M 后速度就跟图形界面复制的速度差不多了。(参见参考链接6

3、Deepin 20.9 的文件管理器默认挂载选项中没有 sync 或之类的参数,在图形界面的文件管理器中应该是同步复制到 U 盘的,复制完毕就可以立即弹出 U 盘,但在命令行中用 cp 命令复制却是像 ubuntu 22.04 那样异步复制的。可能是 Deepin 的文件管理器并不遵守挂载选项的设定,在文件管理器复制文件的行为中作了特别的处理。具体做法未知。

4、Linux 下 NTFS 的驱动有内核驱动 ntfs、ntfs3,用户空间驱动 ntfs-3g,使用不同的驱动加了 sync 参数对速度有比较大的影响。从简单的测试上,从5.15内核开始支持的 ntfs3 的速度是最快的。但未详细的测试。(参见参考链接7

5、flush 和 sync 的挂载参数只适用于部分文件系统,如 flush 好像只适用于 vfat 分区格式。具体未全面测试。

六、小结

Linux 下 U 盘的挂载和数据传输行为受文件系统格式、系统版本、挂载方式、复制方式等多种因素的影响,所以不像 Windows 那样有比较统一的行为。但只要做到一点,就可以保证 Linux 下使用 U盘传输数据的安全性。就是不管什么情况下,拔出U盘前一定要在图形界面弹出U盘,或在命令行下 umount 卸载U盘文件系统。这样就能确保拔出U盘前数据已经在物理介质上保存完毕。

七、参考链接

1、设置是否默认挂载磁盘分区的方式,参见:How to disable automount in nautilus's preferences https://askubuntu.com/questions/89244/how-to-disable-automount-in-nautiluss-preferences
命令行方式:gsettings set org.gnome.desktop.media-handling automount false(或 true)
图形工具:dconf-editor 设置与上面命令同样路径的值。

2、什么是USB写缓存以及怎么禁用U盘的写缓存?(主要是 Windows 的) https://www.usbzh.com/article/detail-348.html
不过,我在 VirtualBox 的 Windows 11 虚拟机中测试了一下,更改了写入缓存策略后好像并没有什么显著的表现变化。

3、udisks2 挂载文件系统,参见:udisks https://wiki.archlinux.org/title/udisks

4、Udisks2 可配置的挂载选项,参见:Configurable mount options of Udisks2 http://storaged.org/doc/udisks2-api/latest/mount_options.html

5、从源码安装 Udisks2,参见:install udisks2 from source on Ubuntu 18.04 https://www.jwillikers.com/install-udisks2-from-source

6、Linux cp 命令使用的数据块大小查看,参见:Efficient File Copying On Linux https://eklitzke.org/efficient-file-copying-on-linux

7、Linux 5.15 内核开始支持的 ntfs3 驱动,参见:PARAGON NTFS3 Driver FAQ NTFS3 IMPLEMENTATION FOR LINUX KERNEL https://www.paragon-software.com/us/home/ntfs3-driver-faq/

发表评论

电子邮件地址不会被公开。 必填项已用*标注