我正在尝试为网络连接硬盘编写设备驱动程序。我想知道锁定/解锁请求队列的正确方法是什么?在哪里?
澄清:
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);
}
但这失败并导致内核锁定。
还有其他想法吗?
答案 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
来实现的。