2016-10-04 243 views
1

我是libusb的新手,所以我不太了解它。我正在尝试做一些USB通信。Libusb在使用C++ 11异步时挂起

我使用的热插拔功能工作得很好。所以我想当我检测到一个设备到达事件时,我会在另一个线程上使用C++11异步功能与USB进行所有通信,因此我可以使用多个设备进行同步I/O以简化代码。他们的异步I/O对我来说有点混乱。希望我可以在C++异步功能中使用同步I/O。

但我有一个问题,当代码运行在C++ 11异步功能中时,某些libusb调用似乎挂起。当它没有运行在C++ 11异步特性中时,它没有任何问题。

所以我假设它是我的C++ 11异步功能代码,这就是问题所在。

这里是我的热插拔回调:

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; 
} 

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

它输出

所以

请注意,这段代码更具原型性,所以它的写法不是很好。它仍处于libusb的探索模式。

回答

3

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

例如,它们特别状态:

libusb_close()将除去从轮询组的文件描述符。这里可能会出现各种各样的竞争条件,所以现在没有人在做事件处理,这一点很重要。

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

的问题是,如果两个或多个线程同时调用的poll()或select()上的libusb的文件描述符则只有一个线程将被唤醒时,一个事件到达。其他人将完全无视任何事情发生。

这是完全可以想象,这里所发生的是,在libusb_handle_events主线程被“偷”的事件libusb_close等待,使得它不会再回来。

底线是,你需要:

  1. 跟随链接的文章,其中详细解释了如何使用多线程使用libusb,或
  2. 理解的libusb的异步API,使改为使用它。
+0

谢谢,我终于找到了他们的异步API – pdiddy