當(dāng)前位置:首頁 > 智能硬件 > 智能硬件
[導(dǎo)讀]討論Windows虛擬設(shè)備驅(qū)動(VXD)技術(shù),并采用此項(xiàng)技術(shù)示范性地做出應(yīng)用于PC串口實(shí)時通信的虛擬驅(qū)動程序,找到一種可以在PC中實(shí)現(xiàn)實(shí)時通信的途徑。

 摘要:討論Windows虛擬設(shè)備驅(qū)動(VXD)技術(shù),并采用此項(xiàng)技術(shù)示范性地做出應(yīng)用于PC串口實(shí)時通信的虛擬驅(qū)動程序,找到一種可以在PC中實(shí)現(xiàn)實(shí)時通信的途徑。

    關(guān)鍵詞:VXD 實(shí)時 串口通信

引言

在微軟的視窗操作系統(tǒng)中,系統(tǒng)內(nèi)核掌管所有的應(yīng)用程序,通過獨(dú)特的任務(wù)調(diào)度算法實(shí)現(xiàn)CPU的分時多任務(wù)處理方式。多任務(wù)處理對大多數(shù)用戶可能是件好事,但是對那些想把實(shí)時通信建立在Windows操作系統(tǒng)上的特殊用戶來說,操作界面的圖形化并不比MS-DOS的單任務(wù)更具吸引力。在視窗操作系統(tǒng)里可以進(jìn)行實(shí)時通信和控制碼?答案是:VXD技術(shù)可以幫我們在獲取友好的人機(jī)界面的同時還擁有很強(qiáng)的實(shí)時性。

1 VXD技術(shù)解析

VXD技術(shù)可追溯到Windows3.1,它的引入就是要讓操作系統(tǒng)實(shí)現(xiàn)多工以及硬件資源的共享。為了支持多個MS-DOS任務(wù)同時執(zhí)行,Windows98讓每個MS-DOS應(yīng)用程序在各自的虛擬機(jī)(VM)上運(yùn)行,各自互不相干;而所有的Widnows應(yīng)用程序卻都在一個虛擬機(jī)上運(yùn)行。圖1所示的結(jié)構(gòu)框圖很好地說明了Windows98的整體架構(gòu)。

圖1中,由眾多的VXD組成系統(tǒng)級代碼處于最底層。其中,處于中心地位的是一名為VMM32的VXD,它負(fù)責(zé)協(xié)調(diào)和管理所有的VXDs。其它VXDs則通過消息機(jī)制(這個消息機(jī)制由VMM32.VXD來維護(hù))彼此聯(lián)系。由所有VXDs開放出的服務(wù)接口(API)組成了一個服務(wù)網(wǎng),它們彼此通過合作的方式,提供Windows98的系統(tǒng)底層驅(qū)動服務(wù)。

從以上Windows98系統(tǒng)架構(gòu)可以看出,要想在視窗平臺下獲取很強(qiáng)的實(shí)時性,僅靠提升應(yīng)用程序線程優(yōu)先級的方法是不夠的。因?yàn)閃in32應(yīng)用程序代碼屬于Ring3級,而VXD代碼則屬于Ring0級;采用VXD撰寫的實(shí)時通信程序可以完全不受代碼限制,可以直接對硬件進(jìn)行操作。VXD的這個特點(diǎn)正是實(shí)時通信建立所必須的。

設(shè)計(jì)實(shí)時通信的VXD前,先解釋以下幾個問題:

①VMM32使用VPICD.VXD虛擬化每個硬件和軟件中斷。VMM32為每個虛擬機(jī)(VM)維護(hù)一個IDT結(jié)構(gòu),當(dāng)中斷發(fā)生時,CPU先保護(hù)中斷現(xiàn)場,然后經(jīng)由當(dāng)前VM的IDT把這個中斷引導(dǎo)至相應(yīng)的中斷處理程式。

中斷的虛擬化,使我們有機(jī)會給每個中斷提供新的中斷處理函數(shù),并可以讓多個硬件共享同一個中斷號。VPICD.VXD為我們提供這些服務(wù)。

②VMM有兩個調(diào)度器,用以在多個線程和VMs之間實(shí)現(xiàn)搶占式多工。主調(diào)度器負(fù)責(zé)選定下一個將被執(zhí)行的線程。這個選擇可以是一個,也可以是多個。然后,主調(diào)度器把選擇結(jié)果送給所謂的時間片調(diào)度器,并由后者完成各個應(yīng)用程序間的時間片分配。調(diào)度器也時應(yīng)用程序經(jīng)由呼叫Win32線程優(yōu)先調(diào)整API(如SetThreadPriority和SetPriorityClass等)做出回應(yīng)。當(dāng)中斷發(fā)生時,VMM32自動提升中斷處理函數(shù)所在VM之優(yōu)先級,保證中斷處理函數(shù)能及時被執(zhí)行。

③VXD和Win32應(yīng)用程序可直接通信。Win32應(yīng)用程序可通過一個系統(tǒng)API(DevicelOControl(…))來呼叫位于底層的VXD為其服務(wù)。在呼叫VXD前,首先必須調(diào)用CreatFile(…)這個API加載該VXD(如果該VXD是一個靜態(tài)VXD,則不用加載)。所有的呼叫動作其實(shí)都通過VMM32完成。VXD也可以通過消息方式和位于上層的Win32應(yīng)用程序通信。She11.VXD為所有希望以消息機(jī)制和Win32應(yīng)用程序通信的VXD提供了這一服務(wù)。

以上是編寫一個串口通信驅(qū)動需要的系統(tǒng)層面知識。對于Windows底層的了解。

2 用VXD實(shí)現(xiàn)一個實(shí)時串口通信驅(qū)動

接下來用VXD技術(shù)實(shí)現(xiàn)一個實(shí)時串行通信的驅(qū)動。這個VXD是一個動態(tài)(Dynamic)VXD,當(dāng)它的服務(wù)被呼叫時,VMM32會動態(tài)加載這個VXD。作者采用的工具是C+98DDK。當(dāng)然也可以使用其它的工具,如MASM6.11(或更高版本)、VtoolsD。用C搭配DDK完成VXD構(gòu)建的好處是,可以使用C語言完成絕大部分的程序,程序比較容易閱讀和維護(hù)。

用C來實(shí)現(xiàn)一個VXD驅(qū)動,需要準(zhǔn)備如下條件:一個.ASM的匯編語言接口文件(在其中定義VXD要處理的系統(tǒng)消息和輸出API),一個.C的函數(shù)實(shí)現(xiàn)文件(在其中完成自己函數(shù)實(shí)體),一個.DEF的定義文件(在其中定義VXD中各個段的別名并匯成一個DDB)和一個.MAK檔(用來編譯并連接生成VXD,可有可無)。在這里,僅給出用C實(shí)現(xiàn)的函數(shù)檔。至于其它的文件,可以從本文所列的參考書目或其它文獻(xiàn)中找到相關(guān)文檔的說明。

這個串口通信驅(qū)動程序的功能是:實(shí)時送出一個Byte的數(shù)據(jù),實(shí)時接收一個Byte的數(shù)據(jù)。作為演示之用,并沒有加入其它代碼。該VXD驅(qū)動主要由如下3個系統(tǒng)消息(由VMM32來維護(hù)和管理)處理函數(shù)組成,其代碼如下:

(1)OnSysDynamicDeviceInit()函數(shù)

BOOL OnSysDynamicDeviceInit()

{ //OnSysDynamicDeviceInit

irqhandle=VPICD_Virtualize_IRQ((DWORD)(&irq4));

if(irqhandle= =0){

return FALSE;

}

return TRUE; //OnSysDynamicDeviceInit

}

該函數(shù)用來完成VXD初始化所做的工作。在本例中,由于實(shí)時監(jiān)視串口中斷的需要,要給COM1的中斷安裝一個自定義的斷服務(wù)函數(shù)。98DDK已經(jīng)提供了這個函數(shù)的C語言版,其原型是HIRQ static VPICD_Virtualize_IRQ(PVID pvid),在vpicd.h中。該函數(shù)需要一個指針作為參數(shù)(指向名為VPICD_IRQ_Descriptor的結(jié)構(gòu)體),函數(shù)傳回一個指向該虛擬IRQ的句柄(該句柄在后來的VPICD服務(wù)中需要提供)。VPICD_IRQ_Descriptor結(jié)構(gòu)體的組成為:

typedef struct VPICD_IRQ_Descriptor{

USHORT VID_IRQ_Number; //IRQ號(0~15)

USHORT VID_Options; //標(biāo)志位選項(xiàng)

ULONG VID_Hw_Int_Proc; //硬件中斷服務(wù)程序的地址

ULONG VID_Virt_Int_Proc; //虛擬中斷服務(wù)程序

ULONG VID_Mask_Change_Proc //Mask Change調(diào)用例程

ULONG VID_IRET_Proc; //IRET調(diào)用例程

ULONG VID_IRET_Time_Out; //在Vm的進(jìn)程優(yōu)先級提升之前的最大等待時間

ULONG VID_Hw_Int_Ref; //硬件中斷服務(wù)程序的數(shù)據(jù)存放地址

}VID;

其中只用到三位。在本例中需要聲明一個名為irq4的全局變量為VID結(jié)構(gòu),并付給如下初值:VID irq4={4,0,hwproc,0,0,0,0,500,0},表示將要虛擬化IRQ4,改變其中斷處理函數(shù)為void hwproc(void),該函數(shù)的原型如下:

void hwproc(void){

_asm{

mov dx,0x3f8

in al,dx

mov byte ptr [readin],al

clc

}

return;

}

在這個中斷處理中,僅僅從COM1的數(shù)據(jù)寄存器(地址為3F8h)中讀取接收到的數(shù)值,并把該數(shù)值存放在一個類型為BYTE、名為readin的內(nèi)存中。

(2)OnSysDynamicDeviceExit()函數(shù)

BOOL OnSysDynamicDeviceExit()

{

VPICD_Force_Default_Behavior(irqhandle);

//解除IRQ4虛擬化

return TRUE;

} //OnSysDynamicDeviceExit

該數(shù)提供了用于善后處理VXD在卸載時需要完成的事件。在本例中,和VXD初始化對應(yīng),需要解除對COM1的中斷IRQ4的虛擬化。作者也是用98DDK在vpicd.h中提供的外包函數(shù)void static_inline VPICD_Force_Default_Behavior(HIRQ hirp)。該函數(shù)唯一需要的參數(shù)便是使用VPICD_Virtualize_IRQ函數(shù)傳回的IRQ句柄。

(3)OnDeviceIoControl()函數(shù)

DWORD OnDeviceIoControl(PDIOCPARAMETERS p){

Switch (p->dwIoControlCode)

{

case 1: //端口寫功能

if(!p->lpvOutBuffer||p->cbOutBuffer<1)

{ //輸出緩存的有效性檢查

return ERROR_INVALID_PARAMETER;

}

if(serial_out((DWORD)(p->lpvInBuffer)))

{ //數(shù)據(jù)發(fā)送

*(BYTE*)(p->lpvOutBuffer)=*(BYTE*)(p->lpvInBuffer);

}

else{

*(BYTE*)(p->lpvOutBuffer)=0;

}

open_int(); //打開com1中斷

return 0;

case 2: //端口讀功能

if(*(BYTE*)reading= =0x00)

{ //數(shù)據(jù)讀入

*(BYTE*)(p->lpvOutBuffer)=0x00;

return 0;

}

*(BTYE*)(p->lpvOutBuffer)=*(BYTE*)(readin);

return 0;

}

return 0;

}

return 0;

}

OnDeviceIoControl函數(shù)用來處理Win32應(yīng)用程序?qū)XD的呼叫。Win32應(yīng)用程序的呼叫會讓VMM32送給該VXD一個系統(tǒng)信息,并傳遞進(jìn)一個DIOCPARAMETERS結(jié)構(gòu)的指針。該結(jié)構(gòu)里包含Win32應(yīng)用程序呼叫時傳遞進(jìn)來的各個參數(shù)。這個結(jié)構(gòu)的組成如下:

Typedef stunct DIOCParams{

DWORD Internall; //指向客戶寄存器的指針

DWORD VMHande; //該VM的句柄

DWORD Internal2; //指向DDB結(jié)構(gòu)的指針

DWORD dwIoConrolCode; //DeviceIoControl例程中呼叫的控制碼

DWOD lpvInBuffer; //DeviceIoControl例程呼叫所傳遞進(jìn)來的輸入緩沖區(qū)地址

DWORD cbInBuffer; //輸入緩沖區(qū)的大小

DWORD lpvOutBuffer; //DeviceIoControl例程呼叫所傳遞進(jìn)來的輸出緩沖區(qū)地址

DWORD cbOutBuffer; //輸出緩沖區(qū)的大小

DWORD lpcbBytesReturned; //拷貝到輸出緩沖區(qū)中的字節(jié)數(shù)(可以為NULL)

DWORD lpOverlapped; //DeviceIoControl例程呼叫所傳遞進(jìn)來的重疊I/O塊結(jié)構(gòu)

DWORD hDevice; //Ring3層呼叫應(yīng)用程序句柄

DWORD tagProcess; //例程標(biāo)簽

}

DIOPARAMETERS;

其中,dwIoControlCode指明了Win32應(yīng)用程序需要VXD提供的哪一項(xiàng)服務(wù)。在本例中采用一個switch-case語句作為服務(wù)入口,如下所示。其中服務(wù)1為讓串口送出一個字節(jié),服務(wù)2為讀取一個已經(jīng)由串口接收的字節(jié)。函數(shù)open_int()是用來初始化串口以便接收字節(jié)數(shù)據(jù);函數(shù)BOOL serial_out(DWORD pBuffer)是讓串口發(fā)出一個字節(jié)。它們的函數(shù)體分別如下:

BOOL serial_out(DWORD pBuffer){

if(pBuffer= =NULL){

return FALSE;

}

_asm {

pushfd

cli

push eax

push edx

mov dx,0x3fb ;設(shè)置COM1的波特率

mov al,0x83

out dx,al

mov dx,0x3f8

mov al,12

out dx,al

mov dx,0x3f9

mov al,0

out dx,al

mov dx,0x3fb ;設(shè)置COM1的線控項(xiàng)

mov al,3

out dx,al

mov dx,0x3f9 ;CMM1關(guān)中斷

mov al,0

out dx,al

mov dx,0x3fa ;關(guān)閉com1的FIFO功能

mov al,0

out dx,al

mov dx,0x3f8 ;字節(jié)發(fā)送

mov al,byte ptr [pBuffer]

out dx,al

pop edx

pop eax

popfd

sti

}

return TRUE;

}

serial_out這個函數(shù)體的實(shí)現(xiàn)是用匯編語言實(shí)現(xiàn)的。因?yàn)樯婕暗胶芏嗟亩丝谔峁┮约癈PU的標(biāo)志(flag)和壓棧操作,因此考慮到用匯編語言編寫會簡化代碼。因?yàn)榇舜趥鬏斨?,用到了關(guān)閉中斷的指令(cli),所以,當(dāng)寫操作所要求完成的任務(wù)很多時,此關(guān)中斷指令會讓程序的實(shí)時性很好地體現(xiàn)出來,但cli指令有效時間過長會導(dǎo)致系統(tǒng)問題,所以還是要謹(jǐn)慎使用。

Void open_int(void){

_asm{

mov dx,0x3f9 ;COM1開中斷

mov al,0x05

out dx,al

}

return;

}

open_int函數(shù)用來把PC串口的中斷設(shè)備按照需要設(shè)立起來。函數(shù)體很簡單,僅改變了地址為3F9h的內(nèi)容,意為設(shè)置Rx data ready和Line status中斷位,以便讓CPU可以及時在COM1的中斷服務(wù)程序里讀取串口接收到的字節(jié)。

以上涉及到串口輸入和輸出的函數(shù)體實(shí)現(xiàn)代碼中,用到了PC16550 UART的資料。

至此,一個可用于實(shí)時串口通信的VXD驅(qū)動程序已經(jīng)完成。由于篇幅所限,不能將其它必要的文檔一同提出來討論。

3 Win32客戶測試程序

有了上述VXD驅(qū)動程序,還需要搭配一個Win32客戶程序來進(jìn)行測試。在網(wǎng)絡(luò)補(bǔ)充版(http://www.dpj.com.cn)中,給出一個筆者在VC6下編制的一個控制臺應(yīng)用程序片斷,以供參考。

現(xiàn)在編制VXD驅(qū)動還沒有一個集成開發(fā)環(huán)境(IDE)。本文的驅(qū)動程序是用VC6.0自帶的編譯器編譯的。由于要編譯匯編文檔,所以還需要把一個MASM匯編器(要求6.0以上版本)及其相關(guān)文檔拷貝到VC6.0的vc98u30446目錄下。

4 結(jié)論

通過以上對VXD技術(shù)的簡要分析以及一個用VXD實(shí)現(xiàn)的通信驅(qū)動可以看出,在Windows操作系統(tǒng)中,采用VXD技術(shù),可以很好地克服由多工帶來的時延問題,很好地解決了在Windows平臺下實(shí)時通信的問題。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉