複製鏈接
請複製以下鏈接發送給好友

vxd

鎖定
vxd是virtual X driver的簡寫,即虛擬設備驅動程序。x代表各種設備的名字,如虛擬鍵盤驅動程序(vkd),虛擬鼠標驅動程序(vmd)等等。
中文名
vxd
外文名
virtual X driver
全    稱
虛擬設備驅動程序
特    有
Windows 9x

vxd程序簡介

虛擬設備驅動程序被簡稱為VxD。x代表各種設備的名字,如虛擬鍵盤驅動程序(vkd),虛擬鼠標驅動程序(vmd)等等。VxD程序是硬件成功初始化的途徑。記得dos程序認為它們擁有系統的一切,當它們在虛擬機中運行時,Windows需要給它們一個實機器的替身。VxD程序就是這些替身。VxD程序通常虛擬一些硬件設備,所以,例如當一個dos程序認為它在同鍵盤通訊時,實際是虛擬鍵盤驅動程序在和dos程序通訊。一個VxD程序通常控制真正的硬件設備並對該設備在各個虛擬機之間的共享進行管理。 儘管如此,並不是説每個VxD程序必須和一個硬件設備相連。雖然VxD程序是用來虛擬硬件設備的,但是我們也可以把VxD程序看作是在第0級別的dll。例如,如果你需要做一些只有在第0級別才能做的工作,你就可以編一個VxD程序來為你完成這個工作。這樣,由於此VxD程序並沒有虛擬任何設備,你就可以把它僅僅看作是你的程序的擴展。
VxD程序是Windows 9x特有的,它在Windows NT下不能運行。所以如果你的程序是依靠VxD的,它就不能被移植到Windows NT平台上去。
VxD是系統中權力最大的實體。由於它們可以對系統作任何事情,所以它們是極度危險的。一個惡意的/錯誤的VxD程序可以毀掉整個系統。對於惡意的/錯誤的VxD程序沒有任何的保護措施。

vxd種類

Windows 95下有兩種VxD:
靜態VxD
動態VxD

vxd靜態VxD

靜態VxD是那些從系統啓動就被加載,在系統關閉之前一直存在於內存中的VxD程序。這種VxD可以追溯至Windows 3.x的時代。動態VxD時只有Windows 9x下才有的。

vxd動態VxD

動態VxD程序可以在需要的時候被加載/卸載。這些程序大多數都是用來控制設置管理器和輸入輸出監視器加載的即插即用設備的。你可以在你的win32應用程序里加載或卸載動態VxD程序。

vxd程序通訊

VxD程序,包括VMM,通過以下三種途徑在相互之間進行通訊:
控制消息
服務API
回調

vxd控制消息

當有VMM感興趣的事件發生時,它就向系統中所有載入的VxD程序發送控制消息。控制消息就像是第三層級別的Windows應用程序的消息。每個VxD程序都有一個接受和處理控制消息的函數,叫做設備控制函數。系統控制消息總共有50多個。控制消息不多的原因是系統中通常加載了很多VxD程序,而每個VxD程序在收到一個控制消息時都要進行處理。如果控制消息太多,就會導致系統停滯。所以控制消息只包括那些與虛擬機有關的重要消息,如:一個虛擬機被創建,被銷燬等等。作為對系統控制消息的附加,一個VxD程序可以定義自己的控制消息,這些消息可以用來和那些能響應這些消息的VxD程序通訊。

vxd服務函數

一個VxD程序,包括VMM在內,通常要導出一系列的被別的VxD程序調用的公共函數,這些函數被稱為VxD服務。調用這些服務的機制和在第三層級別運行的的應用程序有很大的不同:每個導出VxD服務的VxD程序必須有一個唯一的ID,你可以從Microsoft得到一個這樣的ID。這個ID是一個包含了一個VxD唯一的身份驗證的16位的數字,例如: UNDEFINED_DEVICE_ID EQU 00000H
VMM_DEVICE_ID EQU 00001H
DEBUG_DEVICE_ID EQU 00002H
VPICD_DEVICE_ID EQU 00003H
VDMAD_DEVICE_ID EQU 00004H
VTD_DEVICE_ID EQU 00005H你可以看到VMM的ID是1,VPICD的ID是3,等等。VMM用這些ID來找到導出所需VxD服務的VxD程序。當一個VxD程序導出VxD服務時,它把所有服務的地址存在一個表裏面。所以,你還需要通過服務分支表裏面服務的索引來找到你所要的服務。例如,如果你要調用第一個服務,GetVersion服務,你就要指定0(這個索引是從0開始的)。調用VxD服務的實機制包括中斷20h,你的代碼產生一箇中斷20h,並帶有一個雙字的值,這個值包含了設備ID和服務索引。例如,如果你要調用一個VxD程序導出的VxD服務,假設VxD程序設備ID是000DH,服務號碼是1,那麼代碼應該是:
int 20h
dd 000D0001h跟在中斷20H後的雙字的高字包含設備ID。低字是在服務列表中的索引。
當20H中斷執行時,VMM得到了控制權,並馬上檢測跟着的雙字。然後它提出設備ID用來找到VxD程序,用服務索引來定位在那個VxD程序中的所要求的服務的地址。
你可以看到這個操作時很費時的。VMM必須浪費很多時間來定位VxD程序和所要服務的地址,所以VMM作了個小小的 。當中斷20H操作成功後,VMM抓取鏈接。這就是説,VMM用直接的服務調用來替代20H中斷和它後面的雙字。所以上面的20H中斷代碼片斷就被改變成:
call dword ptr [VxD_Service_Address]這個把戲是成功的,因為int 20h+dword加一個雙字用6個字節,正好和call dword ptr結構相等。所以接下來的服務調用是快速而有效的。這個方法具有直接性,簡潔性。在好的一方面,它減輕了VMM和VxD載入器的工作量,因為它們不用定位VxD中所有的服務,那些沒有執行過的服務將會保持原樣。再不那麼好的一方面,一旦一個靜態VxD程序導出的服務被調用,那麼就不可能把這個靜態的VxD程序卸載了。由於VMM把調用鎖定到VxD服務的實際地址上,如果提供這個服務的VxD程序從內存中被卸載了,其他VxD程序調用這個服務時就會很快的因為調用無效的內存地址而導致系統崩潰。沒有辦法來消除抓取的鏈接。這個問題的結論是動態VxD不適合作為服務提供者

vxd回調

回調或者回調函數是在VxD程序中給其他的VxD程序調用的函數,不要把回調函數和VxD服務搞混淆了。回調函數不像服務那樣是公共的,它們是私有函數,VxD在特定的情況下把它們的地址送給其他的VxD程序。例如,當一個VxD程序在處理一個硬件中斷時,由於VMM是不可重入的,這個VxD程序不能使用VxD服務,否則會引起頁面錯誤(重入VMM)。這個VxD程序可以把它自己的一個回調函數的地址給VMM,這樣VMM就可以在能忍受頁面錯誤時調用這個函數。回調函數的想法不是VxD獨有的。許多Windows API都在用。最好的例子也許是窗口函數,你把窗口函數的地址填在WINDCLASS或WINDCLASSEX結構裏並把它當作函數來調用RegisterClass或者RegisterClassEx。當有這個窗口的消息傳來時,Windows就會調用你的窗口函數。另一個例子是窗口接管函數。你的程序把接管函數的地址送給Windows,這樣當你感興趣的事件發生時,Windows就會調用你的接管函數。
上述三種方法是VxD之間通訊的,我們還要講對V86,保護模式和Win32應用程序的接口。