美國微軟公司出品的Windows98以其友好的圖形用戶界面,在我國贏得了廣泛的市場。在給廣大辦公環境工作人員帶來方便的同時,也給不少工程技術人員帶來了一些麻煩。一些原本在DOS下很容易編出的控制硬件的程序,現在在Windows98下就不那么容易實現了。作為一個完善的操作系統也必須能控制硬件,象DOS那樣直接與硬件打交道是Windows98不提倡的。它需要開發專門的硬件設備驅動程序,即通過一系列的虛擬設備驅動程序來管理硬件,如:進行中斷響應、I/O端口讀寫或直接存儲器存?。?a href="http://www.nxhydt.com/tags/dma/" target="_blank">DMA)。Windows98內核管理機制非常復雜,因而編寫虛擬驅動程序也變得十分困難,要想編寫虛擬驅動程序,就必須對Windows98的內核有所了解。
1 Windows98的內核管理機制
在Windows95三年后推出的Windows98雖然擴充了許多新的設備驅動特性,如對AGP、USB、DVD的支持,但在內核上卻和Windows95基本一樣,它們都是基于DOS內核的操作系統。Windows98系統核心(Kernel)由虛擬機管理器(VMM)和VxD(Virtual Device Driver)的集合組成。Kernel提供了900多個服務函數來管理內存、控制物理設備、處理中斷、創建網絡協議棧、管理文件系統等,這些服務函數都可以被自己寫的VxD調用。虛擬機(VM)是一個可運行的任務,包含應用程序、支撐軟件、內存和CPU寄存器。在Windows98下有系統虛擬機和DOS虛擬機兩種。虛擬機管理器(VMM)是在系統級核心運行的32位保護模式操作系統,它運行于Ring0,而且不可重入。VMM主要功能是創建、運行、監控和終止虛擬機。VxD即虛擬設備驅動程序,是用來擴展Windows操作系統功能的一類程序。由于VxD運行在系統的Ring0級,擁有與操作系統同等的級別,所以我們可利用它來支持硬件設備的管理。虛擬可編程中斷控制器(VPICD)是負責管理所有硬件中斷事件的程序,它本身也是一種VxD,能提供缺省的中斷處理函數或者允許其它VxD重載中斷處理函數。
2 Windows98下應用程序權限級別
Intel的80x86CPU系列芯片可在三種模式下工作:實模式、保護模式和V86模式。實模式是MS-DOS的運行環境。Windows98只利用了兩種模式:保護模式和V86模式。保護模式給我們帶來很多優越性,如應用程序不再受1M內存的限制,理論上,在保護模式下,CPU可以進行4096M內存的尋址。但在保護模式下,所有的應用程序都有權限級別(Privilege Level)。權限級別按優先次序分為四等:0、1、2、3。0級是最高級別,操作系統就運行在0級,運行在Ring0級的應用程序可以執行所有的指令并可直接對硬件、中斷和文件系統進行物理訪問。如果應用程序擁有的權限級別是第3級,那么它能執行的指令是有限的,對硬件的很多直接操作是不能實現的。在Windows中,一般的應用程序是運行在Ring3級的(如用Visual C++、Borland C++、Visual Basic、Delphi、C++ Builder等SDK工具開發出的應用程序)。它們享有的權限是最低的,受到了保護模式的摫;它們沒有權限去繞過操作系統直接對硬件操作。
有了權限級別,操作系統就有機會在中斷和I/O操作上產生撔檳鈹效果。由于操作系統的權限為0級,它就可以捕獲權限不為0級的應用程序的中斷和I/O請求,然后建立緩沖隊列,再一一進行串行處理。為了使自己的應用程序也能直接處理硬件,就需要編寫專門的VxD。由于VxD是作為操作系統的組件運行于第0級,因而可以利用它來捕獲特定的硬件操作,完成我們需要的任務。
3 Windows98下虛擬設備驅動程序的開發工具和基本編程方法
微軟為驅動程序的開發提供了設備驅動程序工具箱(DDK),基于匯編語言的編程方式和許多VMM服務都使用寄存器的調用方式,確實非常難學,沒有深厚的匯編語言和硬件基礎很難在短時間里開發出自己的VxD。
程序員可利用C或C++語言編寫自己的VxD,而不必操心許多繁瑣的細節。它的基本編程方法是:用VToolsD自帶的Quick VxD程序快速生成程序框架,在VC++或Borland C++中打開此框架的工程文件,并寫進特定的處理代碼,編譯后就可得到所需的VxD文件。
4 一個中斷程序實例
用VToolsD 2.03、VC++5.0為自制的PC/XT總線擴展卡開發了虛擬設備驅動程序Audcard.vxd。該卡每20ms申請一次中斷,中斷由應用程序動態載入系統的Audcard.vxd響應并加以處理。中斷服務程序ISR(InterruptService Routine)結束后,調用函數Shell_PostMessage()向應用程序窗口發送自定義消息。應用程序接受消息后,再通過函數DeviceIoControl()與VxD的接口函數OnW32DeviceIoControl( )互傳緩沖區數據。程序結束即可動態卸載VxD。
當中斷發生時,處理器轉換為ring0級保護模式。Windows系統并不像DOS那樣通過中斷描述符表IDT(InterruptDescriptorTable)直接指向中斷處理過程,而是由IDT入口指向VMM中的程序。該程序將判斷是否為中斷調用,如果是,則把中斷控制權交給虛擬可編程中斷控制器VPICD(VirtualProgrammable Interrupt ControllerDevice),VPICD實際上是一個重要的VxD。VPICD再將其交給另一個注冊了該中斷的VxD(如Audcard.vxd)來處理。VxD程序是通過調用VPICD服務VPICD_Virtualize_IRQ來注冊中斷的。
虛擬設備驅動程序Audcard.vxd的部分源代碼Audcard.h和Audcard.cpp在網上,此應用程序使用了下列函數:CreateFile()動態加載VxD、CloseHandle()并動態卸載VxD、PreTranslateMessage()截獲消息、DeviceIoControl()與VxD互傳緩沖區數據。虛擬設備驅動程序Audcard.vxd經調試后工作正常,未發生過任何丟失數據或死機的現象。
下面是虛擬設備驅動程序Audcard.vxd的部分源代碼Audcard.h和Audcard.cpp,限于篇幅,由QuickVxD自動生成的Audcard.mak未列出。
①Audcard.h
//AUDCARD.h - include file for VxD AUDCARD
#include
#define DEVICE_CLASS AudcardDevice
#define
AUDCARD_DeviceID UNDEFINED_DEVICE_ID
#define AUDCARD_Init_Order
UNDEFINED_INIT_ORDER#define AUDCARD_Major
#define AUDCARD_Minor 0
#define MY_IRQ 5 //定義5號中斷
class MyHwInt:public VHardwareInt
{
public:
MyHwInt():VHardwareInt(MY_IRQ,0,0,0){}
virtual VOID OnHardwareInt(VMHANDLE);
};
class AudcardDevice :
public VDevice
{
public:
virtual BOOL
OnSysDynamicDeviceInit();
virtual BOOL OnSysDynamicDeviceExit();
virtual DWORD OnW32DeviceIoControl(PIOCTLPARAMS pDIOCParams);
MyHwInt* pMyIRQ;
};
class AudcardVM : public
VVirtualMachine
{
public:
AudcardVM(VMHANDLE hVM);
};
class AudcardThread : public VThread
{
public:
AudcardThread(THREADHANDLE hThread);
};
②Audcard.cpp
//AUDCARD.cpp - main module for VxD AUDCARD
#define DEVICE_MAIN
#include "audcard.h"
Declare_Virtual_Device(AUDCARD)
#define WM_USER_POSTVXD
0x1000
//自定義消息
#undef DEVICE_MAIN
AudcardVM::AudcardVM(VMHANDLE hVM) : VVirtualMachine(hVM) {}
AudcardThread::AudcardThread(THREADHANDLE hThread) :
VThread(hThread) {}
BOOL AudcardDevice::OnSysDynamicDeviceInit()
//動態加載時初始化
{
……//硬件初始化
pMyIRQ=new MyHwInt();
if(pMyIRQ&&pMyIRQ->hook()) //掛接中斷
{
pMyIRQ->physicalUnmask(); //允許中斷
return TRUE;
}
else return FALSE;
}
BOOL
AudcardDevice::OnSysDynamicDeviceExit()
//動態卸載過程
{
delete pMyIRQ;
return TRUE;
}
DWORD
AudcardDevice::OnW32DeviceIoControl(PIOCTLPARAMS pDIOCParams)
//與Win32應用程序的接口函數
{
……
}
VOID
MyHwInt::OnHardwareInt(VMHANDLE hVM)
{
…… // 中斷處理
SHELL_PostMessage(AppWnd,WM_USER_POSTVXD ,0,0,0,NULL);
//向應用程序窗口發送消息
sendPhysicalEOI(); //通知VPICD中斷結束
}
用VToolsD 2.03、VC++ 5.0為自制的PC/XT總線擴展卡開發了虛擬設備驅動程序Audcard.vxd。該卡每20ms申請一次中斷,中斷由應用程序動態載入系統的Audcard.vxd響應并加以處理。中斷服務程序ISR(Interrupt Service Routine)結束后,調用函數Shell_PostMessage( )向應用程序窗口發送自定義消息。應用程序接受消息后,再通過函數DeviceIoControl( )與VxD的接口函數OnW32DeviceIoControl( )互傳緩沖區數據。程序結束即可動態卸載VxD。
這樣一個中斷實例就完成了。
以上實例我們已在VTOOlsD3.01和VC++6中調試通過,并已成功地在我們開發的小型實時光譜能量輻射儀中得到應用。
VxD作為現在流行的編程技術已逐漸受到廣泛的關注,在工程技術中必將有著廣闊的應用前景。學習、使用此技術將在科學研究中給我們帶來便利。
-
微軟
+關注
關注
4文章
6566瀏覽量
103957 -
編程
+關注
關注
88文章
3592瀏覽量
93596
發布評論請先 登錄
相關推薦
評論