我正在尝试在我的块级驱动程序(Linux内核版本2.6.39.1)中实现类似生产者的情况。我的块驱动程序make_request_fn
从用户级应用程序接收struct bio
流。收到这些BIO后,他们排队等候。接下来,我创建一个新的struct bio
,它将保存排队的BIO中存在的所有信息。只有在较低级别驱动程序struct request
中有request_queue
个插槽时,才会提交此新“merged_bio”。与此同时,我的块驱动程序将继续从userlevel应用程序接收BIO并将它们排队(密集的负载情况)。现在,为了减少延迟,我想确保在BIO排队时,包含最旧BIO的批次出列,从而最大限度地减少队列中的空闲时间。我很困惑我应该如何实现这种流水线情况(每个请求延迟较低),其中我的驱动程序make_request_fn
是BIO的生产者,而调用submit_bio()
的函数是这些BIO的使用者。可能的方法包括:
Tasklets - 在struct request
中request_queue
广告位空闲后,让小程序从队列中继续使用BIO。这种方法不起作用,因为tasklet处理函数不是原子的,因为它调用submit_bio()
,后者又调用了schedule()
。
工作队列 - 由于工作队列的处理函数可以休眠,因此它们的延迟可能比tasklet高。这可能会影响我的驱动程序的性能,因为BIO可能会在很多之后提交给较低级别的驱动程序,而不是make_request_fn
实际排队的时间。我不确定对性能的影响有多大(我的驱动程序实现了快速记录设备。)
工作队列的另一个问题是如何以及何时安排工作队列?一旦请求槽可用,就必须提交merged_bio
。因此,必须有某种“信令”机制,一旦struct request
可用,就会安排工作队列。我没有看到如何在没有信令或request_queue
机制的情况下连续监视poll()
的空闲时隙,然后明确地调度工作队列。是的,我们无法从之前完成的BIO的回调函数中调用submit_bio()
。
内核线程 - 我认为这是第三种选择。我对内核线程没有太多了解,但这是我计划如何实现的:我的驱动程序make_request_fn
将继续将BIO排入队列。将创建一个新的内核线程,当struct request
插槽可用时(而不是其他情况),该线程将继续消耗队列 中的BIO。因此,每次调度此内核线程时,它都会检查一个空的请求槽,然后从队列中消耗一批BIO并调用submit_bio()
。
更聪明的东西?
stackoverflow的成员可以帮助我选择一种智能有效的方式来实现这种情况吗?谢谢!
UPDATE :我尝试了workqueue方法,但它只是导致我的内核崩溃(/ var / log / messages包含乱码文本,所以我没有任何日志可以共享)。以下是我如何实现工作队列:
工作队列将使用的数据结构:
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()
,系统崩溃。
有什么想法吗?