I/O 佇列的範例用法

針對連接到系統且受特定驅動程式支援的每個裝置,驅動程式可以使用下列 I/O 佇列和 要求處理常式的組合:

  • 單一預設 I/O 佇列和單一要求處理常式 EvtIoDefault。 架構會將所有裝置的要求傳遞至預設佇列,並呼叫驅動程式的 EvtIoDefault 處理常式,以將每個要求傳遞給驅動程式。

  • 單一、預設的 I/O 佇列和多個要求處理常式,例如 EvtIoReadEvtIoWriteEvtIoDeviceControl。 架構會將所有裝置的要求傳遞至預設佇列。 它會呼叫驅動程式的 EvtIoRead 處理常式來傳遞讀取要求、用來傳遞寫入要求的 EvtIoWrite 處理常式,以及 EvtIoDeviceControl 處理常式來傳遞裝置 I/O 控制要求。

  • 多個 I/O 佇列,例如一個用於讀取要求,另一個用於寫入要求。 針對每個佇列,驅動程式只會提供一個要求處理常式,因為佇列只會接收一種類型的要求。

  • 多個 I/O 佇列,每個佇列都有多個要求處理常式。

範例案例包含:

單一循序 I/O 佇列

如果您要針對一次只能服務讀取和寫入要求的磁片磁碟機撰寫函式驅動程式,則函式驅動程式每個裝置只需要一個 I/O 佇列。

驅動程式可以使用架構在呼叫WdfIoQueueCreate時所建立的預設 I/O 佇列,並將DefaultQueue設定為佇列WDF_IO_QUEUE_CONFIG結構中的TRUE。 在WDF_IO_QUEUE_CONFIG結構中,驅動程式也應該指定:

  • WdfIoQueueDispatchSequential 作為分派方法,因此預設 I/O 佇列會同步將 I/O 要求傳遞給驅動程式。

  • 將接收所有 I/O 要求的單一事件回呼函 式 EvtIoDefault

每當驅動程式的預設 I/O 佇列中提供 I/O 要求時,架構會藉由呼叫驅動程式的 EvtIoDefault 要求處理常式,將要求傳遞給驅動程式。 如果佇列中有另一個可用要求,則架構在驅動程式呼叫先前傳遞要求的 WdfRequestComplete 之前,將不會傳遞它。

多個循序 I/O 佇列和手動佇列

請考慮具有下列特性的序列埠裝置:

  • 它可以同時執行一個讀取作業和一個寫入作業。

  • 它無法以非同步方式執行多個讀取或寫入作業。

  • 它可以接收狀態資訊的裝置 I/O 控制要求。 裝置的驅動程式可能需要很長的時間才能完成其中一些要求, (例如要求等候狀態變更) 。

此裝置的函式驅動程式可以使用每個裝置的多個循序 I/O 佇列。 驅動程式會呼叫 WdfIoQueueCreate 三次:一次建立預設佇列,兩次建立兩次額外的 I/O 佇列。 在每個佇列的 WDF_IO_QUEUE_CONFIG 結構中,驅動程式應該指定:

  • WdfIoQueueDispatchSequential 作為每個佇列的分派方法,讓架構以同步方式將 I/O 要求傳遞給驅動程式。

  • 每個佇列的不同 要求處理常式 (EvtIoDefaultEvtIoReadEvtIoWrite) ,這會接收佇列的 I/O 要求。

呼叫 WdfIoQueueCreate之後,驅動程式可以呼叫 WdfDeviceConfigureRequestDispatching 兩次 - 將所有讀取要求轉送至其中一個額外的佇列,並將所有寫入要求轉送到另一個佇列。

使用此設定時,裝置的預設 I/O 佇列 EvtIoDefault 回呼函式只會接收狀態資訊的裝置 I/O 控制要求。

如果驅動程式必須長期保存狀態要求,它可以建立第四個佇列,並將 WdfIoQueueDispatchManual 指定為分派方法。 當驅動程式收到必須等候的資訊要求時,可以將要求放在這個額外的佇列中,直到狀態資訊變成可用為止。 然後,驅動程式可以從佇列擷取要求並完成。 同時,預設佇列可以將另一個要求傳遞給驅動程式。

單一平行 I/O 佇列

IDE 磁碟控制卡可以重迭某些 I/O 作業,但不能重迭其他作業。 例如,當控制器正在處理一個磁片上的讀取或寫入作業時,它可以將搜尋命令傳送到另一個磁片。 另一方面,不支援多個同時讀取和寫入命令。

此控制器的函式驅動程式必須檢查每個 I/O 要求。 如果驅動程式收到搜尋命令,則必須判斷是否可以處理搜尋命令。 如果:

  • 指定的磁片磁碟機已經忙碌中。

  • 磁片磁碟機正在格式化,因此,沒有其他磁片磁碟機可以作用中。

針對連接到控制器的每個裝置,驅動程式可以呼叫 WdfIoQueueCreate 來建立預設的 I/O 佇列。 在每個佇列的 WDF_IO_QUEUE_CONFIG 結構中,驅動程式應該指定:

  • WdfIoQueueDispatchParallel 作為每個佇列的分派方法,讓架構以非同步方式將 I/O 要求傳遞給驅動程式。

  • 每個佇列的 EvtIoDefault 事件回呼函式,將接收佇列的 I/O 要求。

使用此設定時,會將單一平行 I/O 佇列指派給每個裝置。 驅動程式必須檢查架構從每個 I/O 佇列傳遞的每個 I/O 要求。 如果驅動程式可以立即處理要求,則會這麼做。 否則,驅動程式會呼叫 WdfIoQueueStop,這會導致架構停止傳遞要求,直到驅動程式呼叫 WdfIoQueueStart為止。

多個平行 I/O 佇列

SCSI 主機介面卡是支援非同步、重迭 I/O 作業的裝置範例。 最多 32 個裝置可以連線到介面卡。 請考慮具有下列設定的系統:

  • 連線到 SCSI 介面卡的某些裝置支援「重新選取」,有些則不支援。 如果 SCSI 裝置支援重新選取,則在 I/O 作業期間,裝置可以暫時釋放介面卡,讓介面卡可以服務另一個裝置。 第一部裝置稍後會重新選取自己,以完成其作業。

  • SCSI 介面卡會使用硬體信箱來傳遞驅動程式與裝置之間的要求和回應。 如果裝置已準備好要求,但沒有可用的信箱,裝置必須等候。

為了達到最佳效能,此 SCSI 主機介面卡的函式驅動程式應該會在架構可供使用時立即收到 I/O 要求。 驅動程式必須檢查每個要求,並判斷是否可以立即啟動,或必須延後,直到裝置和資源 (,例如信箱記憶體) 可用為止。

驅動程式應該使用多個平行 I/O 佇列。 針對連接到介面卡的每個裝置,驅動程式會呼叫 WdfIoQueueCreate 來建立預設的 I/O 佇列。 在每個佇列的 WDF_IO_QUEUE_CONFIG 結構中,驅動程式應該指定:

  • WdfIoQueueDispatchParallel 作為每個佇列的分派方法,讓架構以非同步方式將 I/O 要求傳遞給驅動程式。

  • 每個佇列的 EvtIoDefault 事件回呼函式,將接收佇列的 I/O 要求。

每個 I/O 佇列的 EvtIoDefault 回呼函式都必須檢查佇列的 I/O 要求,因為它們已傳遞,並判斷每個要求是否可以立即服務。 如果裝置和系統資源可用,驅動程式會啟動 I/O 作業。 如果裝置或資源無法使用,驅動程式必須呼叫 WdfIoQueueStop 停止傳遞其他要求,直到可以處理目前的要求為止。

您可以選擇性地呼叫 WdfIoQueueCreate ,為每個裝置建立額外的佇列。 然後,驅動程式可以呼叫 WdfRequestForwardToIoQueue ,將某些類型的要求重新排入其他佇列。 當架構從其他佇列傳遞要求時,驅動程式可以在必要時在該佇列上呼叫 WdfIoQueueStop,而不是預設佇列,藉此將延遲傳遞的要求數目或類型降至最低。