gpt4 book ai didi

Linux内核模块通过USB读取GPS设备

转载 作者:IT王子 更新时间:2023-10-29 00:40:41 24 4
gpt4 key购买 nike

我正在编写一个 Linux 内核模块,通过 USB 读出一个 GPS 设备(一个 u-blox NEO-7 ),使用这本书 Linux Device Drivers .

我已经可以成功探测和读取设备中的数据了。但是,同时读取具有多个应用程序的设备时会出现问题(我使用“cat/dev/ublox”无限读取)。当通过“Ctrl + C”取消事件/阅读应用程序时,其他应用程序的下一次阅读尝试失败(确切地说方法调用 usb_submit_urb(...) 返回 -EINVAL).

我在实现中使用了以下想法:

  • 内核模块方法应该是可重入的。因此,我使用互斥锁来保护临界区。例如。只允许一名读者同时阅读。
  • 为了安全资源,我重新使用了 struct urb针对不同的阅读请求(参见explanation)
  • 设备特定的数据(如 USB 端点地址等)保存在名为 ublox_device设备特定的结构中。
  • 提交USB读取请求后,调用进程进入休眠状态,直到调用异步完成处理程序。

我验证了这些想法是否正确实现:我同时运行了“cat/dev/ublox”的两个实例并且我得到了正确的输出(一次只有一个实例访问了关键读取部分)。并且重用“struct urb”也在起作用。两个实例交替读出数据。

仅当通过“Ctrl + C”取消当前事件的实例时才会出现此问题。我可以通过不重用“struct urb”来解决问题,但我想避免这种情况。 IE。通过 usb_alloc_urb(...) 为每个读取请求分配一个新的“struct urb” (通常在探测USB设备时分配一次)。

我的代码遵循 USB skeleton driver来自 Greg Kroah-Hartman,他还针对不同的阅读请求重用了“struct urb”。

也许有人知道这里出了什么问题。

完整代码可以在pastebin上找到.这是读取方法和 USB 请求完成处理程序的一小段摘录。

static ssize_t ublox_read(struct file *file, char *buffer, size_t count, loff_t *pos)
{
struct ublox_device *ublox_device = file->private_data;
...
return_value = mutex_lock_interruptible(&ublox_device->bulk_in_mutex);
if (return_value < 0)
return -EINTR;
...
retry:
usb_fill_bulk_urb(...);

ublox_device->read_in_progress = 1;

/* Next call fails if active application is cancelled via "Ctrl + C" */
return_value = usb_submit_urb(ublox_device->bulk_in_urb, GFP_KERNEL);
if (return_value) {
printk(KERN_ERR "usb_submit_urb(...) failed!\n");
ublox_device->read_in_progress = 0;
goto exit;
}

/* Go to sleep until read operation has finished */
return_value = wait_event_interruptible(ublox_device->bulk_in_wait_queue, (!ublox_device->read_in_progress));
if (return_value < 0)
goto exit;
...
exit:
mutex_unlock(&ublox_device->bulk_in_mutex);
return return_value;
}

static void ublox_read_bulk_callback(struct urb *urb)
{
struct ublox_device *ublox_device = urb->context;
int status = urb->status;

/* Evaluate status... */
...
ublox_device->transferred_bytes = urb->actual_length;
ublox_device->read_in_progress = 0;

wake_up_interruptible(&ublox_device->bulk_in_wait_queue);
}

最佳答案

现在,我为每个读取请求分配一个新的 struct urb。这避免了在调用应用程序取消事件读取请求后出现困惑的 struct urb 问题。分配的结构在完整的处理程序中被释放。

我会回来LKML当我优化我的代码时。现在,可以为每个读取请求分配一个新的 struct urb。内核模块的完整代码在pastebin上.

static ssize_t ublox_read(struct file *file, char *buffer, size_t count, loff_t *pos)
{
struct ublox_device *ublox_device = file->private_data;
...
retry:
ublox_device->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL);
...
usb_fill_bulk_urb(...);
...
return_value = usb_submit_urb(ublox_device->bulk_in_urb, GFP_KERNEL);
...
}

static void ublox_read_bulk_callback(struct urb *urb)
{
struct ublox_device *ublox_device = urb->context;
...
usb_free_urb(ublox_device->bulk_in_urb);
...
}

关于Linux内核模块通过USB读取GPS设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25019058/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com