內核代碼統一使用緩衝塊間接和塊設備(如磁碟)交換數據,緩衝區數據通過塊設備驅動程式和塊設備交換數據。 ...
塊設備驅動程式
塊設備驅動程式負責實現對塊設備數據的讀寫功能。內核代碼統一使用緩衝塊間接和塊設備(如磁碟)交換數據,緩衝區數據通過塊設備驅動程式和塊設備交換數據。
塊設備的管理
塊設備表
內核通過一張塊設備表blk_dev[]管理各種塊設備,每個表項對應一個塊設備,併為每一個塊設備維護一個請求隊列。
- current_request:指向設備請求隊列第一個節點,請求隊列通過鏈表實現。
- request_fn:函數指針,用於處理請求隊列裡面的讀寫請求。
設備請求隊列
內核為每個塊設備維護一個請求隊列,請求隊列中請求等待被處理,current_request指向設備請求隊列。
- 請求項
用於描述請求操作,包含讀寫磁碟扇區位置信息、緩衝區地址信息、操作類別(讀/寫)信息等。
請求項數據結構:
- 請求項數組
一塊連續記憶體,被分割為請求項大小的塊,形成數組,充當記憶體池的角色。請求隊列中的請求項的記憶體從請求項數組中進行分配,請求操作完成後,請求項會被釋放回該記憶體池中。
- 請求隊列
處理讀寫設備請求時,從請求項數組中獲取一個空閑塊,建立請求項,並插入設備請求隊列中。
塊設備操作方式
在內核與塊設備進行數據交換(IO)時,涉及到三個對象之間的交互作用,其中主要需要瞭解系統和控制器之間的交互過程。
- 系統(內核):內核可以向控制器發送命令(發出請求)或等待設備控制器發出中斷請求(完成請求)。
- 控制器:完成讀寫操作後,向系統(CPU)發出中斷。
- 驅動器:受設備控制器控制
寫數據過程
- 系統向控制器發出寫命令後,等待塊設備準備好接收數據,期間CPU需要主動查詢控制器的狀態寄存器判斷是否準備好接收數據(忙等待)。
- 控制器準備好後,CPU將數據寫入控制器的緩存中。(控制器具有一塊緩存)
- 控制器將緩存中的數據通過驅動器全部寫入塊設備。
- 向CPU發出中斷,中斷處理程式完成寫數據後的處理
讀數據過程
- 向控制器發出讀命令
- 控制器讀取磁碟數據到其緩存中
- 向系統發起中斷,中斷處理程式從控制器緩存中取走數據
請求隊列處理過程
ll_rw_block函數將請求放入塊設備請求隊列,設備中斷處理程式會不斷處理請求隊列,直到隊列為空。
- 寫請求的處理過程
-
ll_rw_block為寫請求建立請求項,並插入設備的請求隊列。若插入前隊列為空,則調用請求項操作函數(request_fn)處理當前寫請求,對塊設備進行寫操作。
-
設備塊設備完成一個寫請求後,向CPU發出中斷信號,CPU運行中斷處理函數。
-
中斷處理程式判斷是否還有數據要寫(一個請求會可能寫多個扇區),如果有則繼續寫,然後等待下一次中斷,這一過程重覆直到該寫請求數據全部寫入設備。
-
完成數據寫之後,中斷處理程式將喚醒一些等待進程
- 喚醒等待該請求項有關數據的相關進程
- 喚醒等待請求項的進程(當記憶體池沒有空閑請求項時,將導致某些請求讀寫的進程睡眠)
- 釋放當前請求項並從鏈表中刪除該請求項以及釋放鎖定的相關緩衝區。
-
喚醒等待進程後,中斷處理程式將調用請求項操作函數處理下一個讀/寫請求。
- 讀請求處理過程
與寫請求處理過程類似
- ll_rw_block與中斷處理程式
ll_rw_block,負責將讀寫請求放入隊列中,並啟動對請求隊列的處理。
中斷處理程式,設備完成讀寫操作後,發出中斷,不斷處理請求隊列中的請求操作,直到請求隊列為空。
相關知識
- I/O調度演算法,讀寫請求不是按訪問順序放入請求隊列的,0.11內核使用電梯演算法調度讀寫請求
總結
- 每個塊設備具有一個請求隊列,對塊設備的讀寫請求被插入到隊列中。
- 中斷處理程式不斷處理請求隊列中的請求,直到隊列為空。完成某個請求後,會喚醒一些等待的進程。