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

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

我有一条udev规则,当我将 CF 卡插入 USB 读卡器时,该规则会触发一个 shell 脚本,该脚本会从 CF 卡上复制照片。这在一段时间内效果很好。但最近升级后它停止工作了。

问题(AFAICT)是,将 CF 卡插入 USB 读卡器不再触发任何udev事件,因此我的脚本永远不会运行。 (甚至 中的条目/dev/disk/by-label/也不会显示在插入中,并且dmesg不显示有关插入的任何内容。)

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"

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

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

KERNEL=="sd?", SUBSYSTEM=="block", RUN+="/usr/local/bin/hot-add-disk"

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

更新#2:adduevent 触发器

存在一个开放的、不完整的Debian 错误涵盖了一些类似的领域(跳到更新#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 key来说,/sys/block/sdj只有在插入USB key时才存在。

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

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

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

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

答案1

长话短说:请参阅下面的更新 2 中的解决方案。

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

这就是通常有效的方法及其原因:大多数笔记本电脑 SD 卡读卡器。你会发现你插入一张 SD 卡,udev看到它,Linux 就会扫描它的分区,自动挂载就会正常工作。为什么这有效?看看lsusb插卡前和插卡后的情况。您会注意到,如果未插入 SD 卡,则 USB 设备不存在。因此,当您插入 SD 卡时,就会发生全面的 USB 热插拔事件。

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

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

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

更新#1

以上是 Debian stock 内核的全部内容。我刚刚用 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"

相关内容