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

澄清:

  • 我使用blk_init_queue创建了一个队列,并将请求处理程序函数和我创建的锁(即信号灯)传递给该函数。
  • 我的请求处理程序函数如下所示:
    struct request *req;
    int ret;
    while ((req = blk_fetch_request(q)) != NULL) {
         ret = rb_transfer(req);
    }
    
  • 我的rb_transfer启动一个新的内核线程来处理请求。
  • 处理请求并完成数据传输后,将对该请求调用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);
    }
    

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

    还有其他想法吗?

    最佳答案

    传递给request_fnblk_init_queue通过保持作为第二个参数传递的spinlock并禁用中断来调用。因此,您可以放心地假设没有正在运行的并行线程正在执行request_fn。但是,如果创建一个处理该请求的并行线程,则完全由您负责同步对这些线程中的请求的访问。
    request_fn__blk_run_queue_uncond调用,而__blk_run_queue又由blk_execute_rq_nowait__blk_run_queue函数调用。如果您在Linux内核中搜索调用q->queue_lock的函数,则可以通过持有blk_init_queue(传递给函数ojit_code的自旋锁)来看到所有这些函数。

    10-08 20:02
    查看更多