linux - 在服务请求时将队列锁定在 block 设备驱动程序中的正确方法

标签 linux linux-kernel linux-device-driver

我正在尝试为网络连接的硬盘编写设备驱动程序。我想知道锁定/解锁请求队列的正确方法是什么以及在哪里?

澄清一下:

  1. 我使用 blk_init_queue 创建了一个队列,并将请求处理函数和我创建的锁(即信号量)传递给该函数。
  2. 我的请求处理函数如下所示:

    struct request *req;
    int ret;
    while ((req = blk_fetch_request(q)) != NULL) {
         ret = rb_transfer(req);
    }
    
  3. 我的 rb_transfer 启动了一个新的内核线程来处理请求。

  4. 处理请求并完成数据传输后,将针对该请求调用 blk_end_request_cur

现在,我的问题是如何在上面的循环中保护对请求队列的访问?在一般的驱动程序中?

我试过这样的:

struct request *req;
int ret;
while ((req = blk_fetch_request(q)) != NULL) {
     spin_lock(&lock);
     ret = rb_transfer(req);
     spin_unlock(&lock);
}

但这失败了并导致内核锁定。

还有其他想法吗?

最佳答案

传递给 blk_init_queuerequest_fn 是通过持有作为第二个参数传递的 spinlock 并禁用中断来调用的。因此,您可以放心地假设没有正在运行的并行线程正在执行此 request_fn。但是,如果您创建一个处理此请求的并行线程,那么同步访问这些线程中的请求则完全是您的责任。

request_fn__blk_run_queue_uncond 调用,后者又由函数 __blk_run_queueblk_execute_rq_nowait 调用。如果您在 linux 内核中搜索调用 __blk_run_queue 的函数,您可以看到它们都是通过持有 q->queue_lock 来实现的,这是传递给函数的自旋锁 blk_init_queue

关于linux - 在服务请求时将队列锁定在 block 设备驱动程序中的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19418979/

相关文章:

linux-device-driver - 在 Qemu 上编写用于 DMA 传输的 PCI 驱动程序

linux - linux内核中controller interrupt no和interrupt no的关系

linux - httpd/apachectl 服务无法在 RHEL 7 上启动

linux - netstat 返回奇怪的名称,我希望在其中看到端口号(例如 mcreport(8003 mulberry 报告服务)和 pago-services2(30002))

linux - 如何编写一个shell脚本来添加两个数字?

debugging - ARM Gdb 在处理器模式更改时中断

linux - 即使存在 .config 也使内核提示配置选项

linux - 扩展文件属性和 bash

linux - 修改Linux Kernel中Sysfs的/sys/devices/system/memory/目录

networking - DPDK MLX5 PMD 驱动程序探针问题