2014-12-02 41 views
4

我正在寻找一个Java API,它将允许注册文件系统挂载事件,即文件系统挂载或卸载时。具体而言,我想知道何时可移动USB设备上的文件系统可用,并且也知道它是什么类型的USB设备。java api在安装文件系统时接收通知

udev子系统在USB插头上提供通知,并在默认情况下拔出事件,但不是在设备上的文件系统可用时。可以创建udev规则,这些规则可以分片完成,例如创建目录并在添加和删除设备时执行程序。但是我对udev规则的使用经验是,这个语法很神秘,而且它们很脆弱,不容易调试。每这篇文章

我已经安装了usbmount:

https://serverfault.com/questions/414120/how-to-get-usb-devices-to-automount-in-ubuntu-12-04-server

虽然我相信这些设备是由默认automouting。

作为替代,我构建了一个JDK 7 WatcherService on/media,它可以检测/ etc/mtab中的更改。这种方式很有效,但我曾经看到过一些USB设备上的文件系统还没有准备好的情况 - 这意味着即使在/ etc/mtab中的条目被创建之后,尝试读取该目录的操作也会抛出异常。我添加了一个定时器,可以在一个可配置的毫秒数内进行休眠,并且在大多数情况下,100ms的等待时间可以工作,但不是100%的时间。这意味着增加这个等待时间不是绝对的保证也不是确定性的。

很明显,在某些低级别,正在生成挂载事件,因为显示了Nautilus弹出窗口。我有一个闪存驱动器的情况下,将Nautilus图标放入启动板菜单,但它不会安装,直到单击图标打开。

我也看了一下这些选项:

  • 拖尾的/ var/log/syslog的;这可能是下一个最佳选择。我看到像下面的行:

:12月02日8点58分07秒fred的-灵-530 udisksd [1759]:代表的UID 1000

安装的/ dev/sdk1在/媒体/ fred的/ USB DISK1

我打算在这里尝试一个WatcherService,看看是否存在相同的时间问题,即一旦写入该消息就可以读取目录。

  • jlibudev [github.com/nigelb/jlibudev]好多的Java API来的udev子系统比写规则,但它仍然未能在你仍然有一块多种不同的事件一起。 NB: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。

任何和所有的指针和援助将不胜感激。

回答

1

由于不存在与操作系统无关的方式来处理挂载文件系统,因此肯定没有JDK API。我猜这个问题没有得到太多处理(没有很多程序直接处理挂载文件系统),所以不太可能有任何预建的库在等着你。

在你提到的方法中,它们在平台特定方面(所有Linux都是如此)方面听起来大致相同,所以只留下作为开放问题的性能和易编码性。关于性能,运行lsusb不止一次是(a)一个巨大的黑客:-)和(b)fork + exec相比运行正在处理的内容来说是缓慢的,并且拖尾事件日志将创建大量(不可预知的)为您的程序工作,这与USB挂载无关,并使您的实现更脆弱(如果升级操作系统时消息字符串发生了变化,该怎么办?)。关于编程的简易性,使用jna或JNI调用libudevWatcherService/media声音大约相等 - 使用libudev似乎是跨Linux发行版/用户配置(我猜这就是鹦鹉螺使用的)最便携的选项。

但是,为了简化实施,对于99%的用户来说,这很难做到比WatcherService更好的/media。为了确保文件系统在使用之前可用,我只是使用一个循环,在尝试读取目录之间等待的时间量中使用某种随机指数回退 - 这样,您永远不会等待更长的时间要挂载的文件系统,您不会耗费大量的CPU唤醒并尝试读取,而且您不必选择一个无法在任何地方工作的单个超时编号。如果你足够小心,以确保你不拘束一个线程永远睡觉,我会使用ScheduledExecutorService发出Runnable s试图访问文件系统,如果它不可用安排自己再次运行一次,否则警告您的主线程可以使用某种类型的队列使用新的文件系统。

编辑:我刚刚得知您还可以观察/proc/mounts文件的更新。希望由于内核负责更新这个文件,只有当它们完全挂载时才会显示,尽管我不确定。欲了解更多详情,How to interpret /proc/mounts?the Red Hat docs是有用的。