Block multi-queue 架构解析(一)数据结构

本文介绍了Linux块设备层的Block Multi-Queue (multiqueue)架构,该架构通过为每个CPU分配一个软件队列和每个硬件队列分配一个硬件派发队列,减少锁竞争以提升IO性能。核心数据结构包括bio、request、request_queue、elevator_queue/elevator_type、blk_mq_ctx和blk_mq_hw_ctx。文章详细阐述了这些数据结构的功能和作用,以帮助理解multiqueue如何工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Linux块设备层已逐步切换到multiqueue , Linux5.0以后单队列代码已被完全移除。multiqueue核心思路是为每个CPU分配一个软件队列,为存储设备的每个硬件队列分配一个硬件派发队列,再将软件队列与硬件派发队列做绑定,减少了IO请求过程中对锁的竞争,从而提高IO性能。网上已有很多针对block multiqueue架构的文章,推荐这篇《Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems》。这一系列主要梳理一下block multiqueue的实现,基于Linux5.x。

block mltiqueue 架构,图片引用自《Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems》

核心数据结构

bio

block层的IO最小单元,负责在block层以及其上下层之间传递数据。bio数据结构中除了包含IO的一些基础信息,操作类型(读/写/discard...),作用的磁盘/分区,IO优先级,状态等等。bio最重要的信息是描述了磁盘上一段连续数据与内存页的映射关系,主要由bi_vcnt,bi_io_vec,bi_iter 描述。

struct bio {
	struct bio		*bi_next;	/* request queue link */    //一个request有多个bio时,以单向链表组织bio
	struct gendisk		*bi_disk;
    ...
	struct bvec_iter	bi_iter;    //bvec迭代器
    ...
	unsigned short		bi_vcnt;	/* how many bio_vec's */

	/*
	 * Everything starting with bi_max_vecs will be preserved by bio_reset()
	 */

	unsigned short		bi_max_vecs;	/* max bvl_vecs we can hold */

	atomic_t		__bi_cnt;	/* pin count */  //bio 引用计数

	struct bio_vec		*bi_io_vec;	/* the actual vec list */

	struct bio_set		*bi_pool;

	/*
	 * We can inline a number of vecs at the end of the bio, to avoid
	 * double allocations for a small number of bio_vecs. This member
	 * MUST obviously be kept at the very end of the bio.
	 */
	struct bio_vec		bi_inline_vecs[0];
};

 struct bio_vec :是描述磁盘数据与内存页映射的最小单元,每个bio_vec以offset & size形式描述一个内存页中的一段数据。每个bio 通常有多个bio_vec,bio_vec以数组的形式存储,*bi_io_vec 指向数组头,bi_vcnt记录了其个数。bi_inline_vecs是为每个bio预分配的bio_vec数组,包括4个bio_vec,若bio需要分配的bio_vec小于4可直接使用bi_inline_vecs,不需要再额外申请内存,此时bi_io_vec会指向bi_inline_vecs。

struct bio_vec {
	struct page	*bv_page;
	unsigned int	bv_len;
	unsigned i
Linux block IO(块输入输出)是Linux操作系统的IO子系统,用于管理块设备(例如硬盘和SSD)的访问。在多核系统上引入多队列SSD访问是种优化措施。 传统上,Linux操作系统在处理块设备访问时,使用单个队列(queue)来处理所有IO请求。这种单队列设计对于单核系统来说是合适的,因为只有个CPU核心可以处理IO请求。然而,在多核系统中,这种设计却成为了性能瓶颈,因为所有的IO请求都必须经过单个队列,即使有多个CPU核心是可用的。 为了解决这个问题,Linux引入了多队列SSD访问功能。这意味着在多核系统上,每个CPU核心都有个独立的队列来处理IO请求。每个队列可以独立处理IO请求,而不会受到其他队列的干扰。这种设计可以提高系统的并发性和吞吐量。 多队列SSD访问还可以充分利用SSD设备的性能特点。SSD设备通常具有多个通道(channel)和多个闪存芯片(chip),每个通道和芯片都可以同时处理IO请求。通过将IO请求分配给多个队列,可以同时利用多个通道和芯片,从而提高SSD的性能。 在Linux中实现多队列SSD访问需要对内核进行相应的修改和配置。用户可以通过命令和配置文件来设置每个队列的属性和参数,以满足特定场景下的需求。 总之,通过引入多队列SSD访问,Linux在多核系统上可以更好地利用硬件资源,提高系统的性能和吞吐量。这是个重要的优化措施,可以提高块设备访问的效率和响应速度。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值