Udev 触发器不会在将 CF 卡插入 USB 读卡器时触发(不再)

P.T*_*.T. 6 linux usb debian udev

我有一个udev规则,当我将卡插入我的 USB 读卡器时,触发一个 shell 脚本从我的 CF 卡复制照片。这工作得很好一段时间。但最近升级后,它已停止工作。

问题(AFAICT)是将 CF 卡插入 USB 读卡器不再触发任何udev事件,所以我的脚本永远不会运行。(即使是 in 中的条目/dev/disk/by-label/也不会出现在 insert 上,并且dmesg没有显示任何关于 insert 的信息。)

udev如果我运行fdisk -l /dev/sdf(或sdh它似乎是 CF 卡将出现的任何设备),我可以导致事件触发。我已经udev使用udevadm monitor, 并通过运行验证了事件udevd --debug。在我手动触发系统后,脚本从这里开始工作正常。

我正在运行 Debian 6.0 (Squeeze),我非常有信心是几个月前 Lenny 的升级改变了行为,但我不确定这是否是一些细微的变化udev(也许我在听对于错误的事件?)或内核或 USB 堆栈中的某些更改?无论如何,有人对如何解决这个问题有建议吗?或者从 USB 存储模块中获取更多调试信息的建议?

这是我正在使用的 udev 规则:

KERNEL=="sd??", SUBSYSTEM=="block", RUN+="/usr/local/bin/hot-add"
Run Code Online (Sandbox Code Playgroud)

更新 #1:在 blockdev 和分区更改时触发

我添加了一个规则来仅在块设备上而不是在分区上触发(以防它可能出现),但是当我插入 CF 卡时它也不会触发:

KERNEL=="sd?", SUBSYSTEM=="block", RUN+="/usr/local/bin/hot-add-disk"
Run Code Online (Sandbox Code Playgroud)

奇怪的是,如果我运行fdisk -l /dev/sdf以触​​发对 CF 卡的识别,我会收到一个“已更改”事件/dev/sdf(即使我从未收到过“添加”事件)。

更新 #2:adduevent 触发器

有一个开放的、不完整的Debian 错误涵盖了一些类似的领域(相关位跳到Update#25)。这有一些方便的提示。

对于我的设置,如果我(以 root 身份)echo add > /sys/block/sdf/uevent插入了 CF 卡但无法识别,这将udev正确触发所有事件并且我的所有脚本都正确运行。

udevadm info --query=all --name=sdf插入CF卡前后运行没有区别。如果我注入 'add' 事件并重新运行udevadm命令,我会得到更多输出(有一些关于磁盘分区的信息)。

更新 #3:USB 读卡器中的 USB 密钥与 CF 卡

插入一个普通的 USB 密钥会udev立即触发所有事件并且工作正常。将 CF 卡插入 USB 读卡器不会。对于读卡器,即使没有插入 CF 卡,USB 设备似乎也“存在”(因此/sys/block/sdf存在条目),但是对于 USB 密钥,/sys/block/sdj只有在插入 USB 密钥时才存在。

更新 #4:可能在 2.6.38 中修复

这个Ubuntu 错误有一个更新(最后一个),声称该错误不再存在于 2.6.38 内核中。

更新 #5:未修复(在 3.2.0 中)

我已经升级了几次内核,甚至更换了我正在使用的主板,但我仍然看到同样的问题。我目前使用 3.2.0.0 内核。和udev版本 164。

Wil*_*mer 5

tl;dr:请参阅下面更新 2 中的解决方案。

可悲的是,这并不是一个真正的答案,或者至少不是好消息:我觉得这无论如何都行不通——我只是觉得有点难以置信,因为我肯定认为这在过去是有效的!

这通常是有效的,为什么:大多数笔记本电脑 SD 卡读卡器。你会发现你插入一个 SD 卡,udev看到它,Linux 会扫描它的分区,自动挂载就可以了。为什么这样做?查看lsusb插入卡之前和之后。您会注意到,在没有插入 SD 卡的情况下,USB 设备不存在。因此,当您插入 SD 卡时,就会发生全面的 USB 热插拔事件。

我显示器中的读卡器似乎不是这样工作的,它一直都在。当我插入 SD 卡时,我无法让它生成任何事件。我首先查看系统日志,然后是udevadm monitor,然后usbmon是原始 USB 事件日志记录。运气不好,似乎根本没有任何插入/弹出通知/事件,无论是来自我显示器中的读卡器还是我 PC 中的廉价 DealExtreme 读卡器。

当我尝试访问原始设备时,内核会唤醒并出现分区。同样,调用udevadm trigger它会注意到设备。取出卡,什么也没有发生,直到我再次尝试访问该设备并且内核意识到它已经消失了。

我现在想知道的是,这怎么可能奏效(也就是说,如果我不编造这个记忆)?也许某个守护进程曾经每隔几秒钟轮询一次原始设备并停止这样做?很难找到任何关于此的文档,真的。

更新 #1

以上都是 Debian 股票内核。我刚刚用 Ubuntu 内核做了一些实验,其中 SD 卡热插拔似乎可以工作。毫不奇怪,usbmon我每两秒就会看到一次民意调查。这也解释了为什么没有立即检测到卡片,而是有轻微的延迟。

轮询似乎是由内核完成的,因为它甚至在单用户模式下也会发生,除了陷入select()循环之外,没有用户空间进程做任何事情。我一直无法弄清楚这是在内核中的哪个位置完成的,如果我找到了,我会更新这篇文章。

更新 #2

重要的区别似乎是/sys/block/sd?/events_poll_msecs。在我的 Debian 机器上它是 -1,在 Ubuntu 机器上它是 2000。这条udev规则似乎做到了:

# enable in-kernel media-presence polling
ACTION=="add", SUBSYSTEM=="module", KERNEL=="block", ATTR{parameters/events_dfl_poll_msecs}=="0", ATTR{parameters/events_dfl_poll_msecs}="2000"
ACTION=="add", ATTR{removable}=="1", ATTR{events_poll_msecs}=="-1", ATTR{events_poll_msecs}="2000"
Run Code Online (Sandbox Code Playgroud)