當前位置:學問君>學習教育>畢業論文>

對於設備驅動程序通知應用程序的幾種方法

學問君 人氣:6.07K

在目前流行的Windows操作系統中,設備驅動程序是操縱硬件的最底層軟件接口。爲了共享在設備驅動程序設計過程中的經驗,給出設備驅動程序通知應用程序的5種方法,具體說明每種方法的原理和實現過程,希望能夠給設備驅動程序的設計者提供一些幫助。

對於設備驅動程序通知應用程序的幾種方法

爲了保證操作系統的平安性和穩定性以及應用程序的可移植性,Windows操作系統不答應應用程序直接訪問系統的硬件資源,而是必須藉助於相應的設備驅動程序。設備驅動程序可以直接操作硬件,假如應用程序和設備驅動程序之間實現了雙向通信,也就達到了應用程序控制底層硬件設備的目的。它們之間的通信包括兩個方面摘要:一方面是應用程序傳送給設備驅動程序的數據;另一方面是設備驅動程序發送給應用程序的消息。前者的實現較輕易,透過 CreateFile()函數獲取設備驅動程序的句柄後,就可以使用Win32函數,如DeviceIoControl()、ReadFile()或 WriteFile()等實現應用程序和設備驅動程序之間的通信。後者的實現遠比前者複雜,同時介紹這方面情況的文章較少。這不等於說它不重要,相反,它在有些應用場合發揮着重要的功能。設備驅動程序完成數據的採集工作後,需要馬上通知應用程序,以便應用程序能夠及時將數據取走並進行處理。諸如此類情況,不一而足。

鑑於設備驅動程序通知應用程序的重要性,本人結合一些經驗,對它進行了總結,歸納出5種方法摘要:異步過程調用(APC)、事件方式(VxD)、消息方式、異步I/O方式和事件方式(WDM)。下面分別說明這幾種方式的原理,並給出實現的部分原始碼。

1 異步過程調用(APC)

Win32應用程序使用CreateFile()函數動態加載設備驅動程序,然後定義一個回調函數backFunc(),並且將回調函數的地址%26amp;backFunc()作爲參數,透過DeviceIoControl()傳送給設備驅動程序。設備驅動程序獲得回調函數的`地址後,將它儲存在一個全局變量(如callback)中,同時調用Get_Cur_Thread_Handle()函數獲取它的應用程序線程的句柄,並且將該句柄儲存在一個全局變量(如appthread)中。當條件成熟時,設備驅動程序調用_VWIN32_QueueUserApc()函數,向Win32應用程序發送消息。這個函數帶有三個參數摘要:第一個參數爲回調函數的地址(已經註冊);第二個參數爲傳遞給回調函數的消息;第三個參數爲調用者的線程句柄(已經註冊)。Win32應用程序收到消息後,自動調用回調函數(實際是由設備驅動程序調用)。回調函數的輸入參數是由設備驅動程序填入的,回調函數在這裏主要是對消息進行處理。

2 事件方式(VxD)

首先,Win32應用程序創建一個事件的句柄,稱其爲 Ring3句柄。由於虛擬設備驅動程序使用事件的Ring0句柄,因此,需要創建Ring0句柄。用LoadLibrary()函數加載未公開的動態連結庫,獲得動態連結庫的句柄。然後,調用GetProcAddress(), 找到函數OpenVxDHandle()在動態連結庫中的位置。接着,用OpenVxDHandle()函數將Ring3事件句柄轉化爲Ring0事件句柄。Win32應用程序用CreateFile()函數加載設備驅動程序。假如加載成功,則調用DeviceIoControl()函數將Ring0事件句柄傳給VxD;同時,創建一個輔助線程等待信號變成有信號狀態,本身則可去幹其它的事情。當條件成熟時,VxD置Ring0事件爲有信號狀態(調用 _VWIN32_SetWin32Event()函數),這馬上觸發對應的Ring3事件爲有信號狀態。一旦Ring3事件句柄爲有信號狀態,Win32 應用程序的輔助線程就對這個消息進行相應的處理。

3 消息方式

Win32應用程序調用 CreateFile()函數動態加載虛擬設備驅動程序。加載成功後,透過調用DeviceIoControl()函數將窗體句柄傳送給VxD,VxD利用這個句柄向窗體發消息。當條件滿足時,VxD調用SHELL_PostMessage()函數向Win32應用程序發送消息。要讓該函數使用成功,必須用#define來自訂一個消息,並且也要照樣在應用程序中定義它;還要在消息循環中使用ON_MESSAGE()來定義消息對應的消息處理函數,以便消息產生時,能夠調用消息處理函數。SHELL_PostMessage()函數的第一個參數爲Win32窗體句柄,第二個參數爲消息ID號,第三、四個參數爲發送給消息處理函數的參數,第五、六個參數爲回調函數和傳給它的參數。Win32應用程序收到消息後,對消息進行處理。

4 異步I/O方式

Win32應用程序首先調用CreateFile()函數加載設備驅動程序。在調用該函數時,將倒數第2個偏好設定爲FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,表示以後可以對檔案進行重疊I/O操作。當設備驅動程序檔案創建成功後,創建一個初始態爲無信號、需要手動復位的事件,並且將這個事件傳給類型爲OVERLAPPED的數據結構(如 Overlapped)。然後,將Overlapped作爲一個參數,傳給DeviceIoControl()函數。設備驅動程序把這個I/O請求包(IRP)設定爲掛起狀態,並且設定一個取消例程。假如當前IRP隊列爲空,則將這個IRP傳送給StartIo()例程;否則,將它放到IRP隊列中。設備驅動程序做完這些工作後,結束這個DeviceIoControl()的處理,於是Win32應用程序可能不等待IRP處理完,就從 DeviceIoControl()的調用中返回。透過判定返回值,得到IRP的處理情況。假如當前IRP處於掛起狀態,則主程序先做一些其它的工作,然後調用WaitForSingleObject()或WaitForMultipleObject()函數等待Overlapped中的事件成爲有信號狀態。設備驅動程序在適當的時候處理排隊的IRP,處理完成後,調用IoCompleteRequest()函數。該函數將Overlapped中的事件設定爲有信號狀態。Win32應用程序對這個事件馬上進行響應,退出等待狀態,並且將事件復位爲無信號狀態,然後調用 GetOverlappedResult()

函數獲取IRP的處理結果。

5 事件方式(WDM)

Win32應用程序首先創建一個事件,然後將該事件句柄傳給設備驅動程序,接着創建一個輔助線程,等待事件的有信號狀態,自己則接着幹其它事情。設備驅動程序獲得該事件的句柄後,將它轉換成能夠使用的事件指針,並且把它寄存起來,以便後面使用。當條件具備後,設備驅動程序將事件設定爲有信號狀態,這樣應用程序的輔助線程馬上知道這個消息,於是進行相應的處理。當設備驅動程序不再使用這個事件時,應該解除該事件的指針。

6 結語

在目前流行的Windows操作系統中,設備驅動程序是操縱硬件的最底層軟件接口。它向上提供和硬件無關的用戶接口,向下直接進行I/O、硬件中斷、 DMA和內存訪問等操作。它將應用程序和硬件細節屏蔽開來,使軟件不依靠於硬件並且可在多個不同的平臺之間移植。本文介紹了5種設備驅動程序通知應用程序的方法,其中前3種方法主要用於VxD中,後2種方法主要用於WDM。這5種方法都經過實際測試。測試結果表明,它們都能夠達到設備驅動程序通知應用程序的目的。