生产者消费者在块设备驱动程序中的实现?

我试图实现一个像我的级驱动程序(在Linux内核版本2.6.39.1)的情况下的生产者 – 消费者。 我的块驱动程序的make_request_fn从用户级应用程序接收一个struct biostream。 在收到这些BIO后,他们排队等候。 接下来,我创build了一个新的struct bio ,它将保存排队的BIO中的所有信息。 这个新的“merged_bio”只有在下级驱动程序的request_queue有一个struct request槽可用时才会被提交。 与此同时,我的块驱动程序将继续从用户级应用程序接收BIO,并将它们排队(负载密集的情况)。 现在,为了减less延迟,我想确保当BIO排队时,由最老的BIO组成的批次被排队,从而最小化队列中的空闲时间。 我很困惑,我应该如何实现这种stream水线的情况(低每个请求的延迟),其中我的驱动程序的make_request_fnmake_request_fn的生产者,调用submit_bio()的函数是这些BIO的消费者。 可能的方法包括:

  1. Tasklet – 一旦request_queuestruct request槽变为空闲,就让一个tasklet从队列中持续消耗BIO。 这种方法是行不通的,因为tasklet处理函数不是primefaces的,因为它调用了submit_bio() ,而调用了schedule()

  2. 工作队列 – 由于工作队列的处理函数可以睡眠,所以可能比tasklet具有更高的延迟。 这可能会影响我的驱动程序的性能,因为BIO可能在比make_request_fn实际入队晚的时间提交给较低级别​​的驱动程序。 我不确定影响性能有多大(我的驱动程序实现了快速日志logging设备)。工作队列的另一个问题是如何以及何时安排工作队列? 一旦请求位变得可用, merged_bio必须被提交。 所以,必须有某种“信令”机制,一旦struct request变为可用,就会调度工作队列。 我没有看到request_queue如何在没有信号或poll()机制的情况下连续监视空闲槽,然后显式调度工作队列。 是的,我们不能从之前完成的BIO的callback函数中调用submit_bio()

  3. 内核线程 – 我正在考虑这是第三个选项。 我对内核线程没有太多的了解,但是我打算这么做:我的驱动程序的make_request_fn会继续排列BIO。 一个新的内核线程将被创build, 只有当一个struct request槽变得可用(而不是另外的)时,才会不断地从队列中消耗BIO。 所以,每当这个内核线程被调度时,它将检查一个空的请求槽,然后从队列中消耗一批BIO并调用submit_bio()

  4. 更聪明的东西?

stackoverflow的成员可以帮助我select一个聪明和有效的方式来实现这种情况? 谢谢!

更新 :我尝试了workqueue方法,但它只是导致我的内核崩溃(/ var / log / messages包含乱码文本,所以我没有任何日志分享)。 以下是我如何执行工作stream程:

将由工作队列使用的数据结构:

 struct my_work_struct { struct work_struct wk; pitdev_t *pd; /* Pointer to my block device */ int subdev_index; /* Indexes the disk that is currently in picture -- pd->subdev[subdev_index] */ }; struct pitdev_struct { /* Driver related data */ struct my_work_struct *work; } *pd; typedef struct pitdev_struct pitdev_t; 

初始化我的工作项目:

 /* Allocate memory for both pd and pd->work */ INIT_WORK(&pd->work->wk, my_work_fn); pd->work->pd = pd; pd->work->subdev_index = 0; 

我的工作职能定义:

 void my_work_fn(struct work_struct *work) { struct my_work_struct *temp = container_of(work, struct my_work_struct, wk); pitdev_t *pd = temp->pd; int sub_index = temp->subdev_index; /* Create a BIO and submit it*/ submit_bio(WRITE, merged_bio); } 

merged_bio->bi_end_io ,我安排了我的工作项目:

 schedule_work(&pd->work->wk); 

这样做是为了在上一个BIO成功转移之后不久,提交下一个BIO。 第一次调用submit_bio()是在使用工作队列的情况下完成的。 第一次调用submit_bio()是没有任何问题的, 当我调用使用工作项的submit_bio() ,系统崩溃。

有任何想法吗?