【linux kernel】一文浅析内核的MQ Deadline调度器

备注:新版本的linux(6.10)中只保留了mq-deadline调度器,该调度器保留了较老的deadline调度器的一些特征。本文分析4.19版本内核实现的MQ Deadline调度器。

在MQ Deadline调度器中使用struct deadline_data描述MQ-Deadline调度器的运行时数据,可用于管理和优化存储设备上的请求调度,该结构实现如下:

struct deadline_data {
   
   
	/*
	 * run time data
	 */

	/*
	 * requests (deadline_rq s) are present on both sort_list and fifo_list
	 */
    //红黑树,用于维护请求的排序列表。
	struct rb_root sort_list[2];
    //链表头,用于实现先进先出 (FIFO) 的请求列表。这种列表通常用于按照请求到达的顺序进行调度。
	struct list_head fifo_list[2];

	/*
	 * next in sort order. read, write or both are NULL
	 */
    //用于存储下一个请求的指针数组,可以存储读取请求、写入请求或者两者的组合。
	struct request *next_rq[2];
    //表示连续发出的请求的数量
	unsigned int batching;		/* number of sequential requests made */
    //表示读请求饥饿写请求的次数。可能用于调整读写请求之间的优先级或者调度策略。
	unsigned int starved;		/* times reads have starved writes */

	/*
	 * settings that change how the i/o scheduler behaves
	 */
	int fifo_expire[2];	//FIFO 列表中请求的过期时间。这个设置可能用于确定请求在 FIFO 列表中保留的时间长度。
	int fifo_batch;		//FIFO 列表的批处理大小。可用于控制每次处理 FIFO 列表中请求的数量。
	int writes_starved;	//写请求饥饿的次数。可用于调整写请求的优先级或者调度策略。
	int front_merges;	//前端合并次数。可用于优化请求的合并操作,减少磁盘操作次数。

	spinlock_t lock;
	spinlock_t zone_lock;
	struct list_head dispatch;
};

在内核中,使用struct elevator_type mq_deadline描述MQ Deadline调度器的具体行为:

static struct elevator_type mq_deadline = {
   
   
    .ops.mq = {
   
   
        .insert_requests	= dd_insert_requests,
        .dispatch_request	= dd_dispatch_request,
        .prepare_request	= dd_prepare_request,
        .finish_request		= dd_finish_request,
        .next_request		= elv_rb_latter_request,
        .former_request		= elv_rb_former_request,
        .bio_merge		= dd_bio_merge,
        .request_merge		= dd_request_merge,
        .requests_merged	= dd_merged_requests,
        .request_merged		= dd_request_merged,
        .has_work		= dd_has_work,
        .init_sched		= dd_init_queue,
        .exit_sched		= dd_exit_queue,
    },

    .uses_mq	= true,
    #ifdef CONFIG_BLK_DEBUG_FS
    .queue_debugfs_attrs = deadline_queue_debugfs_attrs,
    #endif
    .elevator_attrs = deadline_attrs,
    .elevator_name = "mq-deadline",
    .elevator_alias = "deadline",
    .elevator_owner = THIS_MODULE,
};

从上述代码可知,该调度器实现了13个具体的调度行为,后文将分析这些回调函数。

一、调度器初始化/注销

MQ-Deadline调度器的初始化由dd_init_queue()完成,用于具体分配并初始化MQ-Deadline调度器的私有数据和电梯队列:

static int dd_init_queue(struct request_queue *q, struct elevator_type *e)
{
   
   
	struct deadline_data *dd;
	struct elevator_queue *eq;

	eq = elevator_alloc(q, e);
	if (!eq)
		return -ENOMEM;

	dd = kzalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
	if (!dd) {
   
   
		kobject_put(&eq->kobj);
		return -ENOMEM;
	}
	eq->elevator_data = dd;

	INIT_LIST_HEAD(&dd->fifo_list[READ]);
	INIT_LIST_HEAD(&dd->fifo_list[WRITE]);
	dd->sort_list[READ] = RB_ROOT;
	dd->sort_list[WRITE] = RB_ROOT;
	dd->fifo_expire[READ] = read_expire;
	dd->fifo_expire[WRITE] = write_expire;
	dd->writes_starved = writes_starved;
	dd->front_merges = 1;
	dd->fifo_batch = fifo_batch;
	spin_lock_init(&dd->lock);
	spin_lock_init(&dd->zone_lock);
	INIT_LIST_HEAD(&dd->dispatch);

	q->elevator = eq;
	return 0;
}

MQ-Deadline调度器的注销由dd_exit_queue()完成:

static void dd_exit_queue(struct elevator_queue *e)
{
   
   
	struct deadline_data *dd = e->elevator_data;

	BUG_ON(!list_empty(&dd->fifo_list[READ]));
	BUG_ON(!list_empty(&dd->fifo_list[WRITE]));

	kfree(dd);
}

在调度器注销操作中则是使用kfree()释放struct deadline_data

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iriczhao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值