文件系统学习8——文件系统MQ队列机制详解

本文详细阐述了Linux文件系统中的MQ多队列机制,从MQ处理结构流图、SCSI设备初始化、request_queue队列初始化、bio请求处理到MQ队列调度器的工作原理,揭示了MQ如何提升IO请求处理效率。通过对源码的分析,介绍了bio请求如何通过软硬件队列映射,最终在硬件队列上执行,并讨论了MQ调度器在多核心CPU环境下的作用。

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

上一篇已经讲述了MQ多队列的机制,利用cpu的多核,配上多队列机制,并发的处理IO请求,提高效率。
本篇详细讲述下从bio下发到IO调度器中,MQ队列机制是如何一步步完成的。

1、MQ处理结构流图

在这里插入图片描述
从整个流程图可以看到,主要是分为三个部分:初始化硬件设备的target参数、初始化请求队列request_queue以及bio请求的处理过程。前面两个过程主要是完成底层存储设备向文件系统的注册,同时完成软硬队列映射关系等初始化,后一个部分是bio在MQ机制最后生成对应子请求并挂载在硬件队列上的过程。

2、scsi设备初始化

对于走scsi协议的底层存储设备,均完成此初始化过程,内核为每个scsi设备提供给一个target的设备参数,该参数主要包括:硬件队列深度,超时时间,硬件中断函数等。
同时,target的设备参数后序作为参数传入requset_queue结构体中,用来初始化硬件队列相关参数。
具体过程如下:
在这里插入图片描述

3、request_queue队列的初始化

之前已经提到过,linux内核支持单队列的机制,也支持多队列的机制,并且在内核中IO调用通过的调用函数都是make_request_fn,那么内核如何知道选用的是多队列机制还是单队列机制呢??
通过make_request_fn函数的注册。

初始化步骤如下:

  • 当底层存储设备是单通道时,此时会向内核make_request_fn注册实体函数,函数名为blk_sq_make_request;当设备是多通道时,此时会向内核make_request_fn注册实体函数,函数名为blk_mq_make_request。
  • 当注册完成后,会根据各自队列的数量,按照内核提供的映射关系,形成cpu号(软件队列号)到硬件队列号的map数组。
  • 按照cpu个数和硬件队列数分别分配软硬件队列环境并进行初始化
  • 将互为映射的软硬件队列环境的参数相互关联。

具体函数流程图如下:
在这里插入图片描述
关于队列初始化的源码阅读如下:
1.首先在driver\scsi文件夹下的scsi_scan.c文件中,scsi_alloc_sdev函数会判断当前scsi支持的块设备是否支持multiqueue:

if (shost_use_blk_mq(shost))    // multiple queue is enabled   gaocm
     sdev->request_queue = scsi_mq_alloc_queue(sdev);    //MQ队列的定义   
 else
     sdev->request_queue = scsi_alloc_queue(sdev);

2.若上述设备支持mq则进入scsi_mq_alloc_queue函数,该函数中主要进行设备队列的初始化,blk_mq_init_queue,在blk_mq_init_queue 函数中根据set信息进行与该设备队列相关的信息参数初始化,过程如下:

  /* mark the queue as mq asap */
   q->mq_ops = set->ops;   //标记为MQ队列   

   q->queue_ctx = alloc_percpu(struct blk_mq_ctx); //获得per_cpu的地址 建立software queue环境 
   if (!q->queue_ctx)
       goto err_exit;

   q->queue_hw_ctx = kzalloc_node(nr_cpu_ids * sizeof(*(q->queue_hw_ctx)),
                       GFP_KERNEL, set->numa_node);    //获得hardware queue上下文环境 
   if (!q->queue_hw_ctx)
       goto err_percpu;

   q->mq_map = blk_mq_make_queue_map(set);   // 建立software queue和hardware queue之间的映射关系 
   if (!q->mq_map)
       goto err_map;

   blk_mq_realloc_hw_ctxs(set, q);
   if (!q->nr_hw_queues)
       goto err_hctxs;

   INIT_WORK(&q->timeout_work, blk_mq_timeout_work);
   blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30 * HZ); //定义scsi设备队列超时设定    

   q->nr_queues = nr_cpu_ids;

   q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT;

   if (!(set->flags & BLK_MQ_F_SG_MERGE))
       q->queue_flags |= 1 << QUEUE_FLAG_NO_SG_MERGE;

   q->
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值