您好,登錄后才能下訂單哦!
本篇內容主要講解“Linux塊層多隊列中如何引入內核”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Linux塊層多隊列中如何引入內核”吧!
首先過目一下多隊列架構:
以讀IO為例,單隊列和多隊列相同的執行路徑:
read_pages() { ... blk_start_plug() /* 進程準備蓄流 */ mapping->a_ops->readpages() /* 蓄流 */ blk_finish_plug() /* 進程開始泄流 */ ... } io_schedule() 進程蓄流之后等待io完成 (在blk_mq_make_request()函數中request的數目大于或者等于16 request_count >= BLK_MAX_REQUEST_COUNT 不需要調用io_schedule(),直接泄流到塊設備驅動)
mapping->a_ops->readpages() 會一直調用q->make_request_fn()
generic_make_request() q->make_request_fn() 調用blk_queue_bio()或者 多隊列blk_queue_make_request() __elv_add_request()
為什么引入多隊列:多隊列相對與單隊列來說,每個cpu上都有一個軟隊列(使用blk_mq_ctx結構表示)避免插入request的時候使用spinlock鎖,而且如今的高速存儲設備,比如支持nvme的ssd(小弟剛買了一塊,速度確實快),訪問延遲非常小,而且本身硬件就支持多隊列,(引入的多隊列使用每個硬件隊列
單隊列插入request時會使用request_queue上的全局spinlock鎖
blk_queue_bio() { ... spin_lock_irq(q->queue_lock); elv_merge() spin_lock_irq(q->queue_lock); ... }
單隊列泄流到塊設備驅動時也是使用request_queue上的全局spinlock鎖:
struct request_queue *blk_alloc_queue_node() INIT_DELAYED_WORK(&q->delay_work, blk_delay_work); blk_delay_work() __blk_run_queue() q->request_fn(q);
__blk_run_queue()函數必須在隊列鎖中,也就是spin_lock_irq(q->queue_lock);
281 * __blk_run_queue - run a single device queue 282 * @q: The queue to run 283 * 284 * Description: 285 * See @blk_run_queue. This variant must be called with the queue lock 286 * held and interrupts disabled. 287 */ 288 void __blk_run_queue(struct request_queue *q) 289 { 290 if (unlikely(blk_queue_stopped(q))) 291 return; 292 293 __blk_run_queue_uncond(q); 294 }
多隊列插入request時沒有使用spinlock鎖:
blk_mq_insert_requests() __blk_mq_insert_request() struct blk_mq_ctx *ctx = rq->mq_ctx; (每cpu上的blk_mq_ctx) list_add_tail(&rq->queuelist, &ctx->rq_list)
多隊列泄流到塊設備驅動也沒有使用spinlock鎖:
static int blk_mq_init_hw_queues() INIT_DELAYED_WORK(&hctx->delayed_work, blk_mq_work_fn); 708 static void blk_mq_work_fn(struct work_struct *work) 709 { 710 struct blk_mq_hw_ctx *hctx; 711 712 hctx = container_of(work, struct blk_mq_hw_ctx, delayed_work.work); 713 __blk_mq_run_hw_queue(hctx); 714 } __blk_mq_run_hw_queue() 沒有spinlock鎖 q->mq_ops->queue_rq(hctx, rq); 執行多隊列上的->queue_rq()回調函數
從下圖可以看出系統使用多隊列之后的性能提升:
(我自己沒測試過性能,憑客觀想象應該與下列圖相符:) )
到此,相信大家對“Linux塊層多隊列中如何引入內核”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。