【问题标题】:Linux: calling open() on a USB device which may not be presentLinux:在可能不存在的 USB 设备上调用 open()
【发布时间】:2015-03-08 23:42:44
【问题描述】:

我有一个连接到 Raspberry Pi 的设备。 Pi 正在运行 ARCH Linux。该设备通过 USB 与 Pi 进行通信。该设备必须通过脉冲打开和关闭,并且我可以从 Pi 控制引起该脉冲的继电器。但是我永远无法确定设备最初是打开还是关闭。

在我的代码中,我切换了继电器,然后推测性地在设备上调用 open()(带有标志 O_RDWR | O_NOCTTY)。问题是,如果我在设备关闭时执行此操作,则 open() 调用会挂起。我曾尝试在切换后等待 1 秒钟,以便解决问题,但这并没有帮助。我曾尝试在 open() 调用之前调用 stat() ,但这总是返回零(因此就 stat() 而言,设备就在那里)。我尝试在 open() 调用中指定 O_NON_BLOCK ,但这会导致它总是失败。

谁能建议(a)我做错了什么或(b)可靠的前进方式?

【问题讨论】:

    标签: linux raspberry-pi


    【解决方案1】:

    如果设备已枚举 USB,则可以确定设备已通电。您可以使用 libudev 查找 USB 枚举设备列表,并检查您的设备是否在该列表中。

    命令行“lsusb”可以做到这一点。所以如果你需要一个如何使用libudev的例子,那么你可以阅读lsusb源代码(https://github.com/gregkh/lsusb)。

    【讨论】:

    • 啊,是的,就是这样,正是我想要的,我应该检查设备是否枚举,而不是愚蠢地尝试 open() 它。非常感谢您将我指向 lsusb 代码,我将从那里继续前进。
    【解决方案2】:

    如果您可以确定设备最终会启动,那么阻塞open()(“挂起”)实际上可能就是您想要的!当您的设备启动时,对open() 的调用将返回,希望成功。

    stat() 调用只是检查设备特殊文件是否存在。它不能告诉你是否有任何东西在听。

    一种可能的前进方式是在指数回退循环中使用open()O_NONBLOCK

    根据您对“通过 USB 通信”的含义,您可能需要使用 libusb。如果它只是一个 USB 串口,那么自己包装 open() 可能是最简单的。

    【讨论】:

    • 不,我使用 open() 来确定设备是否在调用“电源开关”继电器的切换之间存在,我现在意识到这是对 open( )。我应该检查设备是否枚举!
    • 在这种情况下,libusb 将为您节省大量时间/代码。 :) 你可以让它等到你期望的设备枚举然后触发回调。
    【解决方案3】:

    不清楚你做了什么来获得一个在断开连接后仍然存在的设备文件。

    通常的方法是使用hotplug+udev 来创建(和删除)设备符号链接,然后只有在插入设备时才会出现特殊文件。

    【讨论】:

    • 我自己并没有做任何特别的事情,只是让操作系统枚举设备,这可能是问题的一部分。
    • @Rob:枚举设备最多会自动加载驱动程序。您不会自动在文件系统上获取设备特殊文件,即使使用devfs 也不会。你需要一个用户空间服务来做到这一点,很可能是udev(尽管在嵌入式系统上它也可以是busybox mdev)。并且可以配置用户空间服务...
    • 抱歉,是的,我确实有一个自己的规则文件,如果这就是您的意思,它会在 /dev 下弹出一个设备。抱歉我不够清楚,我不必经常这样做和/或一旦它开始工作我就会忘记它:-)。
    • @Rob:好吧,我建议您使用设备删除规则来删除符号链接。拔下设备时。大量相关信息,例如stackoverflow.com/q/1474266/103167unix.stackexchange.com/q/71348/11284unix.stackexchange.com/q/178341/11284
    • 不错,添加ACTION=="remove", ATTRS{interface}=="blah", MODE="7777", SYMLINK-="MySymlink" 设备切换时删除特殊文件关闭,我的代码执行我最初打算现在执行的操作。我想我仍然会做枚举检查,因为这似乎是更正确的事情,但它可以等到我有时间。非常感谢。
    【解决方案4】:

    感谢以下所有乐于助人的人,快速回答是在我的 .rules 文件中包含一个“删除”操作,以配合现有的“添加”操作。所以在我拥有的文件中:

    ACTION=="add", ATTRS{interface}=="Pololu Orangutan X2 Serial Adapter", MODE="7777", SYMLINK+="OrangutanUSB"
    

    ...为了给我一个 /dev/OrangutanUSB 设备,我添加了一个新行:

    ACTION=="remove", ATTRS{interface}=="Pololu Orangutan X2 Serial Adapter", MODE="7777", SYMLINK-="OrangutanUSB"
    

    ...使操作系统在 /dev/OrangutanUSB 设备断电时删除它。这样,当设备离开而不是挂起时,open() 调用会正确失败。

    最终,我应该做的是检查设备是否被枚举,而不是期望 open() 失败,但这可以等到我有时间。现在我的代码按原计划工作。

    【讨论】:

      猜你喜欢
      • 2011-07-02
      • 1970-01-01
      • 2015-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-01
      • 1970-01-01
      相关资源
      最近更新 更多