具有用于用户存储的 USB 端口的设备 - 如何检测/如何允许不安全卸载?

具有用于用户存储的 USB 端口的设备 - 如何检测/如何允许不安全卸载?

我正在尝试构建一个简单的“设备”类型设备,运行最小的 Linux 和一些自定义代码。我提供的部分功能是用户可以将 USB 闪存驱动器或硬盘驱动器连接到特定的 USB 端口,并且设备可以将数据写入该设备上的文件系统。

这个问题有两个部分:


#1:如何确定已连接到某个特定硬件 USB 端口的 USB 大容量存储设备的实际块设备文件?

简单地假设 USB 存储设备始终处于连接状态/dev/sdb似乎有点冒险,因为假设用户将集线器连接到端口,或者假设您获得具有多个端点的设备(例如读卡器)。另外,假设设备重新启动或启动时 USB 端口中有 USB 设备,并且出于某种原因系统决定创建 USB 设备/dev/sda和内部存储/dev/sdb。 (可以想象,该设备的启动介质也将是 USB,因此这很有可能。)

所以我基本上想做的是说“给我 USB 大容量存储设备的设备文件(如 /dev/sdb)具体的USB 端口。”如果在一个端口上找到多个块设备,我需要一个“数组”,或者特定于该单个设备的所有端点的列表。

例如,有人将集线器连接到端口并将多个闪存驱动器连接到该集线器,我可以选择以下任一方法:1)根本不显示任何内容(并告诉用户不允许使用集线器,他们应该只是直接连接),或 2) 获取连接到集线器的所有块设备的列表(类似于多端点设备)。

同样显然,如果有人将非存储设备连接到该端口,那么无论我想出什么方法都不应该给出存储设备节点。


#2:挂载文件系统的最佳实践是什么,以便只要没有发生写入,就可以安全地删除它,而无需先卸载它?

显然,用户会被告知永远不要在设备指示灯闪烁时移除设备等。但是,要求用户执行手动卸载过程对于该设备来说可能是一个糟糕的用户体验。 (它将具有非常小的用户界面,因此实现易于访问和使用的安全删除硬件选项将具有挑战性。)基本上,用户应该能够在视觉上明显看到以下情况时立即将其驱动器拉出:没有更多的写入发生。

显然,大多数连接的设备都是 vfat。我还想支持 ntfs(通过 ntfs-3g)和 exfat(通过 exfat-fuse)。

每当我在自己的代码中写入数据时,我都可以简单地发出同步,但一个用例是外部应用程序,它将数据分块流式传输到 USB 设备。想想数据记录器。创建一个文件并将数据分块传输到该文件,但是之间每个块都应该允许用户在写入之间拉动驱动器,让系统检测到它并干净地停止数据记录,并确保驱动器结构安全。

此外,一旦设备被拉出,我需要快速意识到它,以便我的代码可以删除安装并停止任何可能期望看到驱动器的操作。


我知道我要求很多,以允许用户随意拉动驱动器,显然如果用户拉动驱动器期间写这将是一个问题,但我确实想让至少尽可能接近这个圣杯。

有想法吗?

答案1

对于 (1),我建议查看 udisk——他们已经为您解决了很多问题。包括诸如“如果用户插入时会发生什么”之类的事情存储设备?”(记住:USB 集线器,当然还有一些设备以多个形式出现)。udisks 可让您轻松查找可用设备、在某个设备可用(或被删除)时收到通知、检查各种设备属性等。还将为您处理安装,包括支持各种文件系统。

对于(2),如果可能的话,我会在写入之间卸载设备。如果没有,您可以挂载它sync和/或dirsync模式,这应该会有所帮助 - 这应该使文件系统在写入之间保持一致的状态。此外,如果您写入预先分配的空间,通常不会涉及(或至少很少,仅涉及 mtime)文件系统元数据更改。 (当您创建日志时,写入 10MB 的零;然后返回到开头并将数据流式传输到其中。当您达到 10MB 时,创建另一个日志。只有不频繁的创建操作才会真正面临文件系统损坏的风险。)

不过,正如 Julie Pelletier 指出的那样,某种弹出按钮会更好。

另外,作为旁注,如果您可以让外部应用程序将其数据写入管道(包括使用 创建的命名管道mkfifo),那么您的代码可以从管道中读取数据并处理对 USB 的实际写入。如果您让外部应用程序写入 tmpfs 上的临时文件,则同样适用。

相关内容