Windows CE 6.x驅動程序的新特性

Windows CE 6.x驅動程序的新特性
作者:何宗鍵

來源:http://msdn.microsoft.com/zh-cn/windowsmobile/dd365153.aspx

訪問檢查
訪問檢查是用來檢查函數的調用者是否有足夠的權限去訪問傳遞給這個函數的內存。訪問檢查是很必要的,它可以防止惡意的應用程序利用驅動程序去完成需要特權才能訪問的資源。設備驅動程序由於在 Windows Embedded CE 6.0中處於內核空間所以是一種特權程序,可以訪問很多系統的資源。而工作在用戶態的應用程序卻不是。如果一個應用程序利用設備驅動程序去讀寫系統的內存,那麼設備驅動程序實際上就相當於是授予了這個應用程序高的訪問權限。所以在設備驅動程序中進行訪問檢查可以保護操作系統的內存不受惡意應用程序的破壞。

在 Windows CE 5.0中,設備驅動程序是通過 MapCallerPtr API來對指針參數和嵌套的指針參數進行訪問檢查的。

複製代碼
struct MyStruct { UCHAR *pEmbedded; DWORD dwSize; };
 
// Windows CE 5.0 and prior versions
// In XXX_IOControl...
 
MyStuct *p = ( MyStruct*) pInput;
g_pMappedEmbedded = MapCallerPtr(p->pEmbedded);
// Fail if g_pMappedEmbedded == NULL ...在 Windows Embedded CE 6.0中,設備驅動程序只需要檢查嵌套的指針參數是否有效就可以了。所不同的是在 Windows Embedded CE 6.0中需要使用 CeOpenCallerBuffer這個 API來檢查是否對於某一段內存,調用進程是否有訪問權限。

複製代碼
// Now in the New CE Version
// In XXX_IOControl...
 
hr = CeOpenCallerBuffer((PVOID*)&g_pMappedEmbedded, pInput->pEmbedded, pInput->dwSize, ARG_I_PTR, FALSE);
// Fail if FAILED(hr) == true
 
// When done with pointer...
hr = CeCloseCallerBuffer((PVOID)g_pMappedEmbedded, pInput->pEmbedded, pInput->dwSize, ARG_I_PTR );Marshalling
處於內核態的線程對位於用戶空間的內存的訪問可以分爲兩種方式。同步訪問( Synchronous Access)和異步訪問( Asynchronous Access)。同步訪問是指,當訪問這塊內存區域時,處於內核態的線程是在調用者的上下文環境內。而異步訪問正好相反,設備驅動程序所擁有的一個線程要訪問的一塊內存區域,而該區域正位於其他進程的地址空間中,那麼這就是異步訪問。

舉個異步訪問的例子,比如應用程序通過 WriteFile API來向設備 SD卡中寫入一段數據,最後寫的請求會通過操作系統內核發送到 SD卡的設備驅動中,由設備驅動程序來寫入數據。但是 I/O操作是一個很慢的操作,爲了使 CPU達到高的利用率,內核往往會在這時重新調度一個線程開始執行,這樣用戶空間就可能發生了一次切換。這裏說可能,是因爲如果被調度的線程和當前的應用程序(也就是當前進程)處於同一進程空間的話,那麼就不發生進程的切換,並且要寫入的這段數據由於還是位於當前進程空間中,所以就是對於這塊數據的訪問就是同步的。反之,如果被調度的線程不處於當前進程的空間,那麼就會發生一次進程的切換,新的進程會替換老的進程,這時要寫入的這塊數據區域對於設備驅動程序中的線程來說就是無效的,這也稱爲異步訪問。

對於異步訪問必須採用一種叫 Marshalling的技術來處理被訪問的數據區域。

在 Windows CE 5.0中,所有的用戶態進程共享底部的虛擬地址。所以當 Slot 0中被替換爲不同進程時,由於所有的進程的虛擬地址空間對於設備驅動程序來說都可見,只需要對指向數據塊首地址的指針做一次偏移,就可以得到這塊數據。

在 Windows Embedded CE 6.0中,每個用戶態的進程都有自己獨有的虛擬地址空間,每個進程的虛擬地址空間都是受到保護的。所以對一塊內存做 Marshall不再是簡單的將指針進行偏移。這時可以採用兩種方法來對一塊內存做 Marshall,一種方法是將這塊內存拷貝一份這樣就可以安全的訪問,這種方法稱爲複製。另一種方法是用一個新的虛擬地址去引用所對應的物理,這樣一來這塊數據就分別被兩個指針分別引用,這種方法稱爲別名。

Marshall一塊內存區域需要區分同步訪問和異步訪問。在 Windows CE 5.0中,對於同步訪問來說,不需要做多餘的工作,只需要調用 MapCallerPtr API來 Marshall嵌套指針所指的地址即可。對於異步訪問,線程對於每個 Slot都有一定的訪問權限,所以需要通過調用 SetProcPermissions來先獲得調用進程 Slot的訪問權限,然後調用 MapCallerPtr來 Marshall所要異步訪問的內存。

複製代碼
// Windows CE 5.0 and prior versions
 
// In XXX_IOControl...
   SetProcPermissions(-1);
   g_pMappedEmbedded = MapCallerPtr( p->pEmbedded );
// Fail if g_pMappedEmbedded == NULL ...在 Windows Embedded CE 6.0中,對於同步訪問,通過設備驅動程序通過調用 CeOpenCallerBuffer來 Marshall嵌套指針所指的數據塊的首地址,當這塊數據使用完以後,設備驅動程序調用 CeFreeCallerBuffer來釋放 Marshall所得資源。對於異步訪問,假設設備驅動程序可以同步的訪問一塊內存,那麼這時就可以通過調用 CeAllocAsynchronousBuffer來 Marshall這塊內存用來做異步訪問之用。在使用完之後,可以通過調用CeFreeAsynchronousBuffer來釋放 Marshall所得資源。

複製代碼
// Now in the New OS Version
 
// In XXX_IOControl after CeOpenCallerBuffer generates
// g_pMappedEmbedded...
 
hr = CeAllocAsynchronousBuffer((PVOID*)&g_pMarshalled, g_pMappedEmbedded, pInput->dwSize, ARG_I_PTR);
// Fail if FAILED(hr) == true
 
// When done with pointer...
hr = CeFreeAsynchronousBuffer((PVOID)g_pMarshalled, g_pMappedEmbedded, pInput->dwSize, ARG_I_PTR);
 
// Now call CeCloseCallerBuffer as usual...用戶模式下的驅動程序
在 Windows Embedded CE 6.0之前,設備驅動程序是加載在 device.exe進程之中的,而 device.exe與普通應用程序一樣也是用戶態的進程。所以每次應用程序希望能夠與外設進行交互時,都需要通過操作系統內核轉發請求到相應的驅動程序。這樣一個請求就可以需要反覆的進出內核多次,還需要在不同的進程間進行切換。這樣做的好處和缺點同樣的明顯,優點是操作系統的穩定性得到了提高,不會因爲某個設備驅動中的缺陷而使整個操作系統崩潰。但缺點是完成請求的效率太低。

在 Windows Embedded CE 6.0中,設備驅動程序能夠工作在用戶模式或是內核模式兩種不同的模式。由於在 Windows Embedded CE 6.0新的體系結構中將操作系統關鍵的部件如文件系統 Filesystem.exe、設備驅動程序管理 Device.exe等都移進了操作系統內核之中,驅動程序完成一個請求不再需要在不同的進程下進行切換,也不需要反覆的進出內核,所以內核模式下的驅動程序完成請求的效率將會大大的提高。但是這樣的效率提高也是要有代價的。內核模式下的驅動程序需要有很高的穩定性,任何一個錯誤都可能引起整個操作系統的崩潰。爲了解決這個問題, Windows Embedded CE 6.0中還設計了另一類稱爲用戶模式的設備驅動程序。

Windows Embedded CE 6.0中設計了一個用戶進程 udevice.exe用來加載設備驅動程序。因爲是被用戶態的進程所加載,所以這類驅動程序就工作在用戶空間,這類驅動程序就成爲用戶模式下的設備驅動程序。用戶模式的驅動程序無疑將增加操作系統的穩定性,並且由於這類驅動程序工作在用戶空間,所以能力有限,不能使用諸如 VirtualCopy這樣的特權 API,也不能對系統中的硬件資源有任意的訪問權限。

用戶模式的設備驅動程序還有一個特點就是它們與內核模式的設備驅動程序具有高度的兼容性。一個好的用戶模式的設備驅動程序的源代碼不需要做任何的改動就可以做爲內核模式的設備驅動程序被加載進內核空間。區分用戶模式的設備驅動程序和內核模式的設備驅動程序標誌就是設備驅動程序在系統註冊表中的 Flag值。當 Flag具有 DEVFLAGS_LOAD_AS_USERPROC( 0x10)時,系統會將設備驅動程序加載成用戶模式,如果沒有該標誌就加載成內核模式。

總的來說,用戶模式下的設備驅動程序和內核模式下的設備驅動程序是很相似的。在有了用戶模式設備驅動程序和內核模式設備驅動程序後,在 OEM開發 BSP的過程中,如果採用了某些第三方的,未經充分測試的驅動程序後。可以先將這些驅動程序做爲用戶模式下的設備驅動程序加載到用戶空間,等到整個系統經過測試可以長時間穩定運行後,再將其轉變成內核模式下的驅動程序加載到內核空間以提高整個系統的效率


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/FLandY1982/archive/2010/01/20/5216778.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章