Linux 块设备,Block Layer层架构演变
前言
Block Layer層在整個I/O中負責承上啟下,上接文件系統,下接塊驅動。
我不想直接討論代碼,希望從一個架構的演變來初探一下Block Layer層。
一、1.0版本
首先我們來了解幾個重要的數據結構
1.1 bio
bio代表了一次I/0請求,代表一個塊設備的一個扇區或者多個連續扇區的數據請求,扇區是塊設備的最小訪問單元,bio是文件系統發給Block Layer層的。
1.2 request
request代表塊設備可以處理的一次任務單元,一個request由一個bio或者多個扇區相連的bio組成。
1.3 架構圖
1.4 小結
Block Layer將文件系統提供的bio變成request,然后交給塊設備驅動處理。
二、2.0版本
目前只支持單個進程訪問塊設備。為了可以支持多進程,我們在塊設備驅動中創建一個隊列:request_queue,所有的進程發起bio生成的request,會被投遞到request_queue,塊設備循環處理request_queue中的request。
2.1 request_queue
每一個塊設備都有一個工作隊列,request_queue,保存準備就緒待處理的request。
2.2 架構圖
2.3 小結
這樣子就實現了多個進程同時訪問塊設備,而且在新的一個bio變成request之前,可以先看看該bio能否合并到request_queue的某個request,這樣子就可以提升bio處理的效率。
三、3.0版本
好像看起來2.0已經挺完美了,但是request_queue會有一把鎖控制,如果多個進程短時間發起多個bio,多個進程不斷競爭鎖,這樣子性能不是很好,我們就引入了plug。
3.1 plug
plug翻譯成中文就是塞子,每一個進程會有一個plug,plug是一個request的list,先將一個進程短時間發起的所有bio生成request先堆積到當前進程的plug list,然后在等待特定時機釋放plug中的requests到request_queue,這樣子可以提升bio處理的效率。
3.2 架構圖
3.3 小結
架構越來越完美了,除了上面的流程,在新的一個bio變成request之前,先看看能不能合并到plug里面的某個request中,如果不行在,再看看能否合并到request_queue里面的某個request中,如果不行再變成request,然后放到plug list中,等待積攢一定量之后,統一放置request_queue里面。
四、4.0版本
看起來好像3.0已經很完美了,但是我們會發現3.0有兩個明顯的優化點。
優化點1:
傳統的塊設備是機械磁盤,這種硬件是靠一個磁頭不斷移動進行訪問數據的,如果我們可以把所有request排序,這樣子就可以提升塊設備的訪問效率。
舉個例子:一個外賣員需要送很多外賣到一個辦公樓,他將外賣按樓層排序合并,然后一層層的送,肯定比隨機拿一個外賣,然后一層層的送的速度快。
優化點2:
每個塊設備單位時間處理request的次數是有限的,如果我們可以提升前臺的進程request被處理的優先級,這樣子就可以帶來更好的用戶體驗。
4.1 scheduler
翻譯成中文就是調度器,scheduler就是可以解決上述的兩個優化點,scheduler會在內部創建自定義的各種隊列來存放plug釋放出來的request,然后scheduler對這個所有的request進行一個調度,按照特定的規則再分發給request_queue,讓塊設備處理。
4.2 架構圖
4.3 小結
有了scheduler,我們就可以實現所有request的重新排序甚至合并,還可以對不同進程的request進行不同的優先級控制,目前linux支持的scheduler有:CFQ,deadline等
5、總結
學習Block Layer層,其實就是學習以上幾個重要的部分:bio,request,plug,scheduler,request_queue,而且linux的single-queue架構就是和4.0版的架構差不多,目前手機上基本采用這個single-queue的架構。
linux目前除了支持single-queue,還支持multi-queue,我就不展開講的,整體的結構很類似。
6、尾巴
整個流程好像看起來很爽,其實我們根本沒有關注過進程的調度,我說的進程就是task_struct,多個進程同時發送bio,最后將bio變成request送給了scheduler進行調度,這些代碼運行在各自的進程上,然后scheduler再將request分發給塊設備處理這個又運行在另一個單獨的進程上。如何讓多個進程發完request之后休眠,如何讓塊設備驅動處理完之后喚醒這些休眠的進程。這個喚醒的關鍵點:在于bio結構體中的bio_end_io_t *bi_end_io這個callback函數指針。
? 回復「?籃球的大肚子」進入技術群聊
回復「1024」獲取1000G學習資料
總結
以上是生活随笔為你收集整理的Linux 块设备,Block Layer层架构演变的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux源码分析汇总
- 下一篇: Linux内核自旋锁