在提供请求时锁定块设备驱动程序中队列的正确方法

时间:2013-10-17 05:34:45

标签: 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

  5. 现在,我的问题是如何在上面的循环中保护对请求队列的访问?在一般的司机?

    我试过这样的事情:

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

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

    还有其他想法吗?

1 个答案:

答案 0 :(得分:3)

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

request_fn调用request_fn,其由函数__blk_run_queue_uncond__blk_run_queue调用。如果你在linux内核中搜索调用blk_execute_rq_nowait的函数,你可以看到所有函数都是通过保存传递给函数__blk_run_queue的自旋锁q->queue_lock来实现的。