驅動程式 - Windows Driver Model (WDM) - 教學說明 - 8. Queue IRP的操作步驟



驅動程式作為User Application跟硬體的溝通橋樑,最常遇到的問題就是硬體處理速度不夠快,導致驅動程式需要等待硬體完成後,再繼續處理下一筆資料,但是驅動程式如果要跟User Application溝通這些同步事情,會產生額外的等待時間,因此,為了達到比較好的處理效能,一般驅動程式做會Queue IRP的動作,讓處理的間隔可以縮到最小,這也是這篇教學要說明的東西

首先要考慮的事情就是,IRP應該儲存在哪裡呢?簡單的作法可以使用Windows驅動程式提供的List相關API,操作步驟如下:
1. InitializeListHead()
2. InsertHeadList()
3. IsListEmpty()
4. RemoveHeadList()

IRP是處裡資料的最小單位,一個IRP代表一筆需要處理的資料,因此,當硬體來不及處理資料時,驅動程式需要做Pending IRP的動作,讓User Application知道這筆資料稍後處理,Pending IRP的步驟如下:
1. IoMarkIrpPending()
2. IoCompleteRequest(STATUS_PENDING)

User Application如何知道資料是否處理完畢或者被Pending了呢?在CreateFile()時,如果沒有用FILE_FLAG_OVERLAPPED,則代表每一筆資料都是必須完成才會回傳,此種寫法也稱為Blocking方式,如:呼叫WriteFile()後,必須等待驅動程式完成該IRP後,WriteFile()才會完成並且繼續往下執行,否則呼叫WriteFile()後,會卡在這個Win32 API,相反地,如果CreateFile()使用FILE_FLAG_OVERLAPPED,而呼叫WriteFile()時,驅動程式回傳Pending,則WriteFile()會馬上回傳ERROR_IO_PENDING,告知User Application,該筆資料驅動程式會稍後處裡,此種寫法也稱為Non-Blocking方式,那如何得知該筆資料處理完畢了呢?當使用Non-Blocking寫法,會在WriteFile()傳入一個OVERLAPPED參數,該參數裡面有一個Event,用來告知是否已經處理完畢

Queue IRP流程:
1. InsertHeadList()
2. IoMarkIrpPending()
3. IoCompleteRequest(STATUS_PENDING)
4. IsListEmpty()
5. RemoveHeadList()
6. IoCompleteRequest(STATUS_SUCCESS)