成人午夜激情影院,小视频免费在线观看,国产精品夜夜嗨,欧美日韩精品一区二区在线播放

虛擬設備驅動程序兩關鍵問題之VXD虛擬化

2010-08-28 10:45:15來源:西部e網作者:

  在虛擬設備驅動程序(VxD)的設計中,兩個尤為關鍵,且又令人困擾的問題是VxD的虛擬化和VxD與應用程序間的通信機制。下面,對這兩個問題作一詳細的探討。

  一、VxD的虛擬化

  由于Windows允許同時運行多個任務,所以出現多個進程試圖同時訪問同一物理設備的情況時,如果多個應用程序通過同一個DLL驅動程序(注意和虛擬設備驅動程序VxD的區別)訪問設備,不需要對該設備虛擬化,驅動程序使之順序訪問;如果是多個Windows應用程序對相同設備同時訪問,由于都運行于System VM(系統虛擬機),所以也不需要虛擬化,它們的訪問將由一個驅動程序(Windows driver DLL)進行檢測并使之串行化,而不是依靠VxD;如果多個VM試圖訪問同一設備,由于DOS應用程序能夠直接操縱硬件,所以必須對該設備進行虛擬化,一個虛擬化設備的VxD負責可靠地檢測多個VM試圖訪問同一設備的情況,并采取仲裁的策略來解決這種沖突。這里可能有以下幾種解決方案:

  1、允許一個VM訪問物理設備,同時忽略其它的VM。這是最簡單的虛擬化形式。如VPD(Virtual Printer Device)。

  2、允許一個VM訪問物理設備,同時為其它的VM虛擬化設備。如VKD(Virtual Keyboard Device)分配給一個VM,并使之獲得物理鍵盤的訪問權(包括鍵盤中斷在內),對其它的VM而言,VKD只向它們提供一個空的鍵盤緩沖區。

  3、允許多個VM共享同一物理設備。盡管存在假象,但從VM的觀點來看,這種方法與獨享訪問一樣。如VDD(Virtual Display Device),使每一個Windows環境下的DOS VM認為是直接寫入顯存,其實只是被VDD映射到了一個窗口的緩沖區。

  4、VxD獨立訪問物理設備的同時,允許一個VM訪問虛擬設備,這是最復雜的虛擬化形式。如VCD(Virtual Com Device),VCD緩沖區接收串行數據并通過映射中斷透明地傳給相應的一個VM,VM在中斷處理過程中讀取串口數據寄存器,這些數據的實質是VCD緩沖區已經接收的數據。

  與物理設備一樣,硬件中斷很多時候也必須虛擬化,這種情況更為復雜。虛擬化中斷實質上就是將硬件產生的中斷映射到需要它的每一個VM(不管該VM是否正在運行),替代VxD進行服務。在這里我們給出一個虛擬化中斷的VxD實例的幾個重要回調過程,并采用最簡單的仲裁策略來解決訪問沖突(見程序1)。

  typedef struct
  {
 IRQHANDLE IrqHandle;
  VMHANDLE VMOwner;
  Char DeviceName[8];
  BOOL bVMIsServicing;
  } DEVICE_CONTEXT;

  void _stdcall MaskChangHandler ( VMHANDLE hVM , IRQHANDLE hIRQ , BOOL bMasking )

  //當一個VM在中斷控制器中屏蔽或打開中斷hIRQ時,VPICD調用該過程

  {
  if ( !bMasking ) //若為打開中斷
  {
  if ( !device.VMOwner )
  {
  device.VMOwner = hVM; //若無任何VM占有該中斷,則將該中斷的擁有權設為當前VM
  }
  else
  {
  if ( device.VMOwner != hVM )
  {
  device.VMOwner = SHELL_Resolve_Contention ( device.VMOwner , hVM , device.DeviceName );

  //若已有VM占有該中斷,則用戶可通過對話框在兩者間作出選擇

  }
  }
  VPICD_Physically_Unmask ( hIRQ ); //打開該物理中斷
  }
  else
  {
  device.VMOwner = 0;
  VPICD_Physically_Mask ( hIRQ ); //屏蔽該物理中斷
  }
  }

  BOOL _stdcall HwIntHandler ( VMHANDLE hVM , IRQHANDLE hIRQ )

  //當中斷hIRQ發生,VPICD立即調用該過程

  {
  if ( device.VMOwner && !device.bVMIsServicing ) //若有VM占有該中斷并且不在上一次的中斷處理中
  {
  VPICD_Set_Int_Request ( device.VMOwner , hIRQ ); //請見本例程后的討論
  }
  else
  {
  ......
  }
  return TRUE;
  }

  void _stdcall VirtIntHandler ( VMHANDLE hVM , IRQHANDLE hIRQ )

  //當VPICD每次向VM模擬中斷時,調用該過程

  {

  device.bVMIsServicing = TRUE; //設置中斷處理標志

  }

  void _stdcall IRETHandler ( VMHANDLE hVM , IRQHANDLE hIRQ )

  //當從VM的中斷處理返回,執行該回調

  {
  device.bVMIsServicing = FALSE; //清除中斷處理標志
   }
  (程序1)


  由于中斷是異步產生的,所以當VxD調用VPICD(虛擬可編程中斷控制器)服務VPICD_Set_Int_Request將該中斷映射到VM時,該VM應處于執行狀態。

  (1)在映射的第一步,VPICD通過調用VMM(虛擬機管理器)服務Call_Priority_VM_Event強制調度所希望的VM,使用最高的優先權(Time_Critical_Boost);

  (2)VPICD提供一個該服務的回調,所以當VM被調度運行時,VMM即可通知VPICD;

  (3)然后VPICD通過調用另一個VMM服務Simulate_Int來調整VM的運行環境。該服務將VM的CS、IP和標志寄存器壓入VM的堆棧,從VM的中斷向量表IVT取出新的CS、IP和標志寄存器,并且清除中斷標志;

  (4)當VPICD從回調返回,并且VMM變回V86模式時,VM便立即執行已向VPICD注冊的中斷處理過程。

  編寫虛擬化設備的VxD與編寫非虛擬化設備的VxD有很大的不同,主要是它要用到一組完全不同的VMM和VxD服務。實際上,現在很多為新設備所編寫的VxD根本就不再虛擬化,因為并沒有DOS或Windows應用程序直接訪問這些硬件。

  二、VxD與應用程序間的通信機制

  由于VxD并不僅僅處理硬件,所以在大多數情形下,VxD還向應用程序提供一個接口。通過該接口,應用程序就能夠做與硬件有關的事情了。

  Windows 9x具有VxD與應用程序雙向通信的機制。下面敘述的應用程序均指Win32應用程序。

  應用程序到VxD的通信機制是:VxD并不象Win16應用程序接口那樣輸出一個特殊的API過程(保護模式API過程或V86模式API過程)來支持應用程序,取而代之的是它的控制過程必須能夠處理一個特殊的消息:W32_DEVICEIOCONTROL。VMM代替調用DeviceIoControl函數的應用程序向VxD發送此消息。消息參數可確定VxD消息響應函數、輸入輸出緩沖區指針及緩沖區大小,并綁定在DIOCPARAMETERS結構中。通過這一接口,不僅僅可以讀寫設備,而且還能在應用程序和VxD之間互傳指針,從而達到特殊應用的目的。

  有時只需調用應用程序與VxD間的接口,便能及時獲得所需信息和服務。但還有一些特殊情況,必須由VxD異步通知應用程序,這就需要用到VxD到應用程序的通信機制。

  VxD到應用程序的接口關系要比應用程序到VxD的接口關系復雜得多。其間有兩種調用方法:一種是使用PostMessage函數。通過調用這一由外殼VxD(SHELL VxD)提供的新服務,便可通知應用程序;另一種是使用特殊的Win32技術。這種技術的獨到之處在于Win32 API支持多線程。

  在Win32技術中,盡管采用的APC(Asynchronous Procedure Calls)異步過程調用機制和Win32事件機制都依賴于喚醒一個Win32應用程序線程,但仍略有不同。VxD到應用程序最簡單的通信機制就是通過APC,這種方法對應用程序和VxD相對要簡單一些。應用程序首先動態加載VxD(CreateFile),并用DeviceIoControl將回調函數的地址傳給VxD,然后應用程序執行Win32調用SleepEx將其自身置為“掛起”(asleep yet alertable)狀態時。

  當應用程序處于“掛起”狀態,VxD能夠通過VWIN32 VxD提供的QueueUserApc服務調用應用程序的回調函數。另一種更有效的方法是使用Win32事件機制。如果應用程序運行多個線程,當子線程等待著VxD來喚醒它的同時,主線程能夠繼續做自己的工作。例如,當一個子線程在等待VxD緩存接收的數據時,主線程可同時監控用戶的輸入。一旦緩沖區達到門限,VxD將喚醒等待的子線程。對于線程間的通知,VxD使用線程事件,就象應用程序的多線程機制所做的那樣。

  在Windows 95下,VxD可訪問與多線程應用程序非常相同的一些Win32事件API(由VWIN32 VxD提供)。這些VWIN32事件服務包括:_VWIN32_ResetWin32Event、_VWIN32_SetWin32Event、_VWIN32_PulseWin32Event、_VWIN32_WaitSingleObject、_VWIN32_WaitMultipleObjects。利用這些服務,VxD可喚醒一個等待的Win32應用程序線程,或是等待被一個Win32應用程序線程喚醒。不幸的是VxD不只是通過簡單調用相應的事件服務,就能夠獲得Win32事件的句柄。因此,為獲得Win32事件的句柄要涉及到一個復雜的過程和一個未公布的系統調用。事件通常是由應用程序產生(Win32 API CreateEvent),然后使用未公布的Win32 API函數OpenVxDHandle將獲得的事件句柄轉換為VxD事件句柄,再通過DeviceIoControl將這一ring 0級事件句柄傳給VxD,于是VxD便可將其作為VWIN32事件函數的參數來使用。

關鍵詞:驅動
主站蜘蛛池模板: 鹤岗市| 开鲁县| 武穴市| 鄂州市| 友谊县| 慈溪市| 南雄市| 舒兰市| 普洱| 和龙市| 仁化县| 交口县| 松江区| 炉霍县| 孝昌县| 保山市| 铁力市| 普定县| 曲沃县| 中方县| 广安市| 西城区| 康平县| 松阳县| 荔浦县| 锦屏县| 昭觉县| 额敏县| 元阳县| 洪江市| 台山市| 通化市| 富川| 平昌县| 尤溪县| 石泉县| 宁海县| 芒康县| 泽州县| 阳谷县| 凌源市|