c++ - 使用 C++11 异步时 Libusb 挂起

标签 c++ multithreading c++11 libusb-1.0

我是 libusb 的新手,所以我不是很了解它。我正在尝试进行一些 USB 通信。

我正在使用效果很好的热插拔功能。所以我想当我检测到设备到达事件时,我会使用 C++11 在另一个线程上与 USB 进行所有通信。异步功能,因此我可以使用多个设备进行同步 I/O 以简化代码。他们的异步 I/O 让我有点困惑。希望我可以使用具有 C++ 异步功能的同步 I/O。

但我遇到了一个问题,当代码在 C++11 异步功能中运行时,某些 libusb 调用似乎挂起。当它不在 C++11 异步功能中运行时,它可以正常工作。

所以我假设问题出在我的 C++11 异步功能代码上。

这是我的热插拔回调:

int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
  std::future<void> result(std::async([] (libusb_device *d) {

    libusb_device_handle *h;

    printf("%s\n", "Opening");
    int rc = libusb_open(d, &h);
    if(rc != LIBUSB_SUCCESS) {
      printf("ERROR: %s\n", libusb_error_name(rc));
      return;
    }
    printf("%s\n", "Opened");

    printf("%s\n", "Closing");
    libusb_close(h);
    printf("%s\n", "Closed!");

  }, dev));

  result.get();

  return 0;
}

所以使用这段代码它卡在 libusb_close

输出:

Opening
Opened
Closing

主要代码如下:

int main(int argc, char* argv[]) {

  int vendor_id = 0x1234;
  int product_id = 0x4556;

  libusb_hotplug_callback_handle *hp = nullptr;
  libusb_context *context = nullptr;
  int rc = libusb_init(&context);

  if(rc < 0)
  {
    return rc;
  }

  libusb_set_debug(context, LIBUSB_LOG_LEVEL_WARNING);

  rc = libusb_hotplug_register_callback(
    context,
    LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
    LIBUSB_HOTPLUG_NO_FLAGS,
    vendor_id,
    product_id,
    LIBUSB_HOTPLUG_MATCH_ANY,
    hotplug_callback,
    NULL,
    hp
    );

  if (LIBUSB_SUCCESS != rc) {
    libusb_exit (context);
    return rc;
  }

  while(1) {
    rc = libusb_handle_events(context);
  }

  return 0;
}

请注意,这段代码比较典型,所以写得不是很好。目前还处于libusb的探索模式。

最佳答案

According to their own website ,使用 libusb 的多线程(如果 std::async 不是序列化的,则本质上是多线程)需要考虑很多。

例如,他们特别声明:

libusb_close() will remove a file descriptor from the poll set. There are all kinds of race conditions that could arise here, so it is important that nobody is doing event handling at this time.

在您的代码中,一个线程中对 libusb_close 的调用与另一个线程中对 libusb_handle_events 的调用之间没有同步。相关(来自与上述相同的来源):

The issue is that if two or more threads are concurrently calling poll() or select() on libusb's file descriptors then only one of those threads will be woken up when an event arrives. The others will be completely oblivious that anything has happened.

完全可以想象,这里发生的是主线程中的libusb_handle_events正在“窃取”libusb_close正在等待的事件,使其永远不会返回。

底线是您需要:

  1. 按照链接的文章进行操作,该文章详细解释了如何将 libusb 与多线程一起使用,或者
  2. 了解 libusb 的异步 API 并加以利用。

关于c++ - 使用 C++11 异步时 Libusb 挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39861085/

相关文章:

c++ - 菱形继承(钻石问题)——调用所有父函数

c++ - std::thread 请解释输出

java - 使用 'this' 与另一个对象作为同步块(synchronized block)中的等待和通知锁

c++ - 您将如何在 C++11 中实现自己的读/写锁?

c++ - 在 C++ 中将函数指针转换为仿函数

c++ - std::vector 的高效直接初始化

c++ - 在其他类中访问和更改成员变量

c++ - 如何翻转 IplImage

c++ - std::array 派生类聚合初始化

c++ - 链表中的后增量运算符