我正在寻找一个允许注册文件系统挂载事件的Java API,即在挂载或卸载文件系统时。具体来说,我想知道可移动USB设备上的文件系统何时可用,并且还确切知道它是什么类型的USB设备。
默认情况下,udev子系统提供有关USB插拔的事件通知,但在设备上的文件系统可用时则不具体。可以创建可以分段执行此操作的udev规则,例如在添加和删除设备时创建目录并执行程序。但是我对udev规则的体验是语法是晦涩的,它们很脆弱,不易调试。
我已经按照这个帖子安装了usbmount:
https://serverfault.com/questions/414120/how-to-get-usb-devices-to-automount-in-ubuntu-12-04-server
虽然我认为这些设备默认是自动挂载。
作为替代方案,我在/ media上构建了一个JDK 7 WatcherService,可以检测/ etc / mtab中的更改。这有效但我已经看到某些USB设备上的文件系统仍然没有准备好的情况 - 这意味着尝试读取目录会抛出异常 - 即使在/ etc / mtab中输入后也是如此。我添加了一个计时器来睡眠一段可配置的毫秒数,在大多数情况下,100毫秒的等待时间可以工作但不是100%的时间。这意味着增加这个等待时间不是绝对的保证,也不是确定性的。
显然,在某个较低级别,正在生成mount事件,因为显示了Nautilus弹出窗口。我有一个闪存驱动器的情况,将Nautilus图标放在启动板菜单中,但在点击图标打开之前它不会挂载。
我也看过这些选项:
:Dec 2 08:58:07 fred-Inspiron-530 udisksd [1759]:在/ media / fred / USB DISK1上代表uid 1000安装/ dev / sdk1
我将在这里尝试一个WatcherService来查看是否存在相同的计时问题,即写入此消息后该目录是否可读。
jlibudev [github.com/nigelb/jlibudev] udev子系统的Java API比编写规则要好得多,但它仍然不足,因为你仍然需要将许多不同的事件拼凑在一起。注意:jlibudev依赖于JNA [https://github.com/twall/jna]和purejavacomm [github.com/nyholku/purejavacomm,sparetimelabs.com/purejavacomm/purejavacomm.php]这两者本身都非常有用。
lsusb提供有关USB设备的详细信息,但没有提供有关安装位置的详细信息。
理想情况下,我想要一个简单的API,允许使用标准的Java事件监听模式注册文件系统挂载/卸载事件。我想相信这样的API存在或者至少是可能的,因为在宏观层面上,净效应正在发生。我仍在搜索JDK 7和JDK 8 API以获取其他选项。
非常感谢任何指针和帮助。
答案 0 :(得分:1)
由于没有与操作系统无关的方法来处理挂载文件系统,因此肯定没有JDK API。我猜这个问题没有得到很多处理(很多程序都没有直接处理文件系统),所以不太可能有任何预建的库在那里等着你。
在您提到的方法中,它们在特定于平台的方式(所有仅限Linux)方面听起来大致相同,因此只是将性能和编码的简易性留作开放性问题。关于性能,每秒运行lsusb
超过一次是(a)一个巨大的黑客:-)和(b)fork + exec与在进程中运行的东西相比很慢,并且拖尾事件日志将创建很多您的程序的(不可预测的)工作与USB挂载无关,以及使您的实现更加脆弱(如果在升级操作系统时消息字符串发生了变化怎么办?)。关于编程的简易性,使用jna
或JNI呼叫libudev
或WatcherService
/media
声音大约相等 - 使用libudev
似乎是最Linux发行版/用户配置的可移植选项(我猜这是Nautilus使用的)。
但是,为了简化实施,99%的用户可以使用,因此很难比WatcherService
上的/media
做得更好。为了帮助确保文件系统在使用之前可用,我只需要在尝试读取目录之间等待的时间内使用某种随机指数退避的循环 - 这样你永远不会等待比要安装的文件系统,你没有燃烧大量的CPU唤醒和尝试读取,你不必选择一个无法在任何地方工作的超时数。如果您足够谨慎以确保不会让一个线程永远沉睡,我会使用ScheduledExecutorService
来发出试图访问文件系统的Runnable
,如果它不可用则安排自己稍微再次运行,否则使用某种队列警告主线程新文件系统可供使用。
修改:我刚刚了解到您还可以查看/proc/mounts
文件的更新。希望由于内核负责更新此文件,因此只有在完全挂载时才会显示,但我不确定。有关详细信息,How to interpret /proc/mounts?和the Red Hat docs非常有用。