前言:想要寫出一篇令人眼前一亮的文章嗎?我們特意為您整理了5篇驅(qū)動程序設(shè)計范文,相信會為您的寫作帶來幫助,發(fā)現(xiàn)更多的寫作思路和靈感。
關(guān)鍵詞:WDF PCI 中斷 驅(qū)動程序 同步時鐘卡
中圖分類號:TP336 文獻(xiàn)標(biāo)識碼:A 文章編號:1007-9416(2015)05-0000-00
Abstract:This paper introduces the design of Device Drivers of PCI synchronous clock card based on WDF model. Briefly introduces the system architecture and works on our own PCI synchronous clock card, and Analysis the framework of the WDF model and the design process. Focused on the research and development of the WDF Device Drivers based on the PCI synchronous clock card, including hardware access, Interrupt notification. The driver has passed the test for stability and reliability.
Key words: WDF; PCI; interrupt; driver; synchronous clock card.
時間是科學(xué)實驗、科學(xué)研究和工程技術(shù)等領(lǐng)域中的一個基本物理參量。為了保證系統(tǒng)各部分時間的一致性和正確性,系統(tǒng)內(nèi)各設(shè)備的同步時鐘從卡從時鐘源獲取高精度的標(biāo)準(zhǔn)時間,提供給相應(yīng)設(shè)備。這樣系統(tǒng)內(nèi)各設(shè)備的時間與時間源相同而保持一致。同步時鐘卡一般采用PCI總線方式。PCI總線能夠?qū)崿F(xiàn)設(shè)備間的快速訪問,它以突出的性能受到計算機(jī)和通信界工程師們的青睞。
因此如何開發(fā)出穩(wěn)定、可靠、高效的PCI設(shè)備驅(qū)動程序成為驅(qū)動工程師們面臨的一個棘手的問題[5]。過去對于PCI設(shè)備驅(qū)動程序的開發(fā)大多采用WDM(Windows Driver Model)框架,但是它編程比較復(fù)雜,快速掌握其開發(fā)要領(lǐng)對于初學(xué)者來說比較困難[5]。本文所述的PCI同步時鐘卡的驅(qū)動程序的開發(fā)采用微軟最新推出的WDF(Windows Driver Foundation)驅(qū)動模型。WDF驅(qū)動模型提供事件驅(qū)動和面向?qū)ο蟮尿?qū)動程序開發(fā)框架,大大降低了設(shè)備驅(qū)動程序的開發(fā)難度[5]。
1 同步時鐘卡系統(tǒng)架構(gòu)
本文所述的驅(qū)動程序是基于自行研發(fā)的PCI同步時鐘卡,其原理框圖如圖1所示。本同步時鐘卡選擇PCI9052芯片做為PCI總線的接口芯片。該電路除了用到PCI9052外,還用到了單片機(jī)、EEPROM、雙口RAM、CPLD。單片機(jī)是系統(tǒng)的控制單元;串行EEPROM存儲了PCI9052芯片所需要的配置信息;雙口RAM用于PC機(jī)與時鐘卡之間交換數(shù)據(jù);CPLD用于200us時標(biāo)的產(chǎn)生和中斷的控制。
同步時鐘卡的工作流程如下:同步時鐘從卡接收時鐘源輸出的時間信號,單片機(jī)將其解析成高精度的同步時間信息,控制邏輯(CPLD)通過1PPS脈沖信號產(chǎn)生200us的高精度時間刻度,于是產(chǎn)生高精度的同步絕對時標(biāo),連續(xù)存儲于雙口RAM中,最后計算機(jī)通過PCI總線接口獲取高精度的絕對時間。本系統(tǒng)中計算機(jī)獲取雙口RAM中的時間數(shù)據(jù)的方式有兩種:(1)PC機(jī)主動讀取雙口RAM中的數(shù)據(jù)。(2)外部事件通過中斷通知PC機(jī)事件發(fā)生,PC機(jī)收到通知后讀取雙口RAM中的時間信息,可獲得外部事件發(fā)生的精確時刻。兩種方式分別涉及驅(qū)動程序的硬件訪問和中斷通知。于是涉及到本文介紹的重點:基于WDF模型的PCI總線驅(qū)動程序的開發(fā)。
2 WDF驅(qū)動程序設(shè)計
微軟對過去的WDM(Windows Driver Model)驅(qū)動程序的架構(gòu)做了改進(jìn),形成了全新的WDF(Windows Driver Foundation)框架結(jié)構(gòu)。它將原來普通軟件開發(fā)中面向?qū)ο蟮募夹g(shù)應(yīng)用到了驅(qū)動程序的開發(fā)中。WDF改變了驅(qū)動程序與操作系統(tǒng)內(nèi)核之間的關(guān)系,在傳統(tǒng)的WDM驅(qū)動程序中,不僅要處理硬件,還要處理驅(qū)動程序與操作系統(tǒng)內(nèi)核之間的交互[4]?,F(xiàn)在WDF則使驅(qū)動程序與操作系統(tǒng)內(nèi)核獨立開來,驅(qū)動程序與操作系統(tǒng)交互工作將由框架內(nèi)封裝的方法(函數(shù))去完成,這樣驅(qū)動開發(fā)工程師只需專注處理目標(biāo)硬件的行為即可,避免了兩面不周顧此失彼的弊端。不僅大大降低了驅(qū)動程序的代碼量,還使整個系統(tǒng)更加穩(wěn)定、可靠。
WDF驅(qū)動程序包括兩個類型,一個是內(nèi)核級的,稱為KMDF(Kernel-Mode Driver Framework);另一個是用戶級的,稱為UMDF(User-Mode Driver Framework)。本文所述的驅(qū)動程序采用KMDF模式。
2.1 WDF驅(qū)動程序開發(fā)流程
本文所用開發(fā)環(huán)境為Microsoft Windows Driver Kit(WDK) 8.1和Microsoft Visual Studio 2013,操作系統(tǒng)為Windows7。先安裝VS2013,再安裝WDK8.1,便可在VS2013中直接創(chuàng)建KMDF工程。根據(jù)同步時鐘卡所需功能編寫好驅(qū)動程序即可進(jìn)行編譯。
WDF驅(qū)動程序框圖如圖2所示。
2.2 基于WDF模型的PCI設(shè)備驅(qū)動程序的實現(xiàn)
WDF模型的設(shè)備驅(qū)動程序從功能上可分為三個部分:初始化設(shè)備、控制設(shè)置與交換數(shù)據(jù)[3]。初始化設(shè)備主要實現(xiàn)設(shè)備的識別、驅(qū)動對象與設(shè)備對象的建立與硬件資源的分配;控制設(shè)置負(fù)責(zé)應(yīng)用程序與驅(qū)動程序的連接和設(shè)備的打開;交換數(shù)據(jù)處理的是設(shè)備功能的具體應(yīng)用,即PCI總線與同步時鐘卡之間的數(shù)據(jù)傳輸。
從本質(zhì)上來說,WDF模型的設(shè)備驅(qū)動程序是由入口函數(shù)DriverEntry和事件例程及其子函數(shù)組成的[3]。操作系統(tǒng)在第一次加載驅(qū)動程序時會通過調(diào)用DriverEntry例程來完成設(shè)備驅(qū)動程序和框架的初始化[3]。所有的驅(qū)動程序都必須包含一個DriverEntry例程。對于不同類型的驅(qū)動程序其入口函數(shù)DriverEntry也不同,可分為:設(shè)備驅(qū)動、純軟件驅(qū)動與過濾驅(qū)動。本文所述的PCI總線驅(qū)動程序?qū)儆谠O(shè)備驅(qū)動,在入口函數(shù)DriverEntry中,主要完成兩件事:注冊EvtDriverDeviceAdd回調(diào)例程、創(chuàng)建和初始化WDFDRIVER對象。
WDF_DRIVER_CONFIG_INIT(&config,PCIdriverEvtDeviceAdd);
//注冊EvtDriverDeviceAdd回調(diào)例程
status = WdfDriverCreate(DriverObject, RegistryPath,...);
//創(chuàng)建驅(qū)動對象
2.2.1初始化設(shè)備
在驅(qū)動程序被成功初始化完成之后,操作系統(tǒng)會順序調(diào)用EvtDriverDeviceAdd、EvtDevicePrepareHardware等回調(diào)例程以實現(xiàn)所控制的設(shè)備的初始化。
當(dāng)首次枚舉設(shè)備時,EvtDriverDeviceAdd例程在系統(tǒng)初始化時被PnP管理器調(diào)用。在系統(tǒng)運行過程中,任何時候一個新的相同設(shè)備被枚舉,系統(tǒng)都將調(diào)用此例程。EvtDriverDeviceAdd例程是設(shè)備初始化過程中最新被調(diào)用的回調(diào)例程,它需要完成:設(shè)備對象的創(chuàng)建,創(chuàng)建符號鏈接或設(shè)備對象GUID接口,創(chuàng)建一個或多個I/O隊列,各種事件的回調(diào)函數(shù)的注冊,如即插即用、電源管理、I/O處理例程等[1]。
EvtDriverDeviceAdd例程的主要代碼如下所示:
注冊即插即用基本例程:
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
pnpPowerCallbacks.EvtDevicePrepareHardware = PCIDriverEvtDevicePrepareHardware;
pnpPowerCallbacks.EvtDeviceReleaseHardware = PCIDriverEvtDeviceReleaseHardware;
..........
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
創(chuàng)建設(shè)備對象:
WDF_FILEOBJECT_CONFIG_INIT(&f_config,...);
WdfDeviceInitSetFileObjectConfig(DeviceInit, &f_config,WDF_NO_OBJECT_ATTRIBUTES);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, ..);
status = WdfDeviceCreate(&DeviceInit, &attributes, &control_device);
創(chuàng)建隊列對象并注冊回調(diào)例程:
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,....);
ioQueueConfig.EvtIoDeviceControl = PCIdriverEvtIoDeviceControl;
ioQueueConfig.EvtIoStop = PCIdriverEvtIoStop;
status = WdfIoQueueCreate(control_device,&ioQueueConfig,...);
創(chuàng)建符號鏈接:
status = WdfDeviceCreateSymbolicLink(control_device, &ustring);
創(chuàng)建中斷對象:
deviceContext = GetDeviceContext(control_device);
WDF_INTERRUPT_CONFIG_INIT(&interruptConfig,PCIDriverEvtInterruptIsr,
PCIDriverEvtInterruptDpc);//設(shè)置中斷服務(wù)例程和延遲過程調(diào)用WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&interruptAttributes,..);
status = WdfInterruptCreate(control_device,&interruptConfig,
&interruptAttributes,&deviceContext->Interrupt);
EvtDriverDeviceAdd例程調(diào)用完成之后,系統(tǒng)將調(diào)用EvtDevicePrepareHardware例程初始化地址指針,將設(shè)備所占用的I/O地址和內(nèi)存地址映射為虛擬地址,驅(qū)動程序?qū)⑼ㄟ^這些虛擬地址完成與設(shè)備的數(shù)據(jù)傳輸。由于串行EEPROM存儲了PCI9052芯片所需要的配置信息,系統(tǒng)將自動為本文所述的PCI同步時鐘卡分配資源,它們包括雙口RAM的內(nèi)存地址、PCI9052的I/O地址空間,所以EvtDevicePrepareHardware例程必須將這些資源映射為虛擬地址。對于I/O端口,只需將首地址與地址數(shù)目值保存在設(shè)備上下文;對于存儲器芯片,調(diào)用MmMapIoSpace函數(shù)將物理地址映射為系統(tǒng)內(nèi)核虛擬地址,然后保存于設(shè)備上下文。相對應(yīng)的,當(dāng)設(shè)備被卸載時,系統(tǒng)會自動調(diào)用EvtDeviceReleaseHardware回調(diào)例程釋放之前申請的硬件資源。
for (i = 0; i < WdfCmResourceListGetCount(ResourceListTranslated); i++) {//WdfCmResourceListGetDescriptor函數(shù)獲取該資源的描述符
descri = WdfCmResourceListGetDescriptor(ResourceListTranslated, i);
switch (descri->Type)
{case CmResourceTypeMemory:
Mem_Count++;
if (Mem_Count == 2)//將雙口RAM地址映射為虛擬地址
{pDevice_context->MemBaseAddress = MmMapIoSpace(
descri->u.Memory.Start,
descri->u.Memory.Length,
MmNonCached);
pDevice_context->MemLength = descri->u.Memory.Length;}
break;
case CmResourceTypePort://將PCI9052的I/O地址映射為虛擬地址
pDevice_context->Io_baseAddress = descri->u.Port.Start.LowPart;
pDevice_context->Io_length = descri->u.Port.Length;
default:
break;}}
2.2.2控制設(shè)置與數(shù)據(jù)交換
應(yīng)用程序?qū)崿F(xiàn)和驅(qū)動程序通信的過程是:應(yīng)用程序首先調(diào)用CreateFile函數(shù)打開設(shè)備,然后可以使用DeviceIoControl和驅(qū)動程序通信,包括寫數(shù)據(jù)給驅(qū)動程序和從驅(qū)動程序讀數(shù)據(jù)兩種情況,也可以用WriteFile寫數(shù)據(jù)給驅(qū)動程序或用ReadFile從驅(qū)動程序讀數(shù)據(jù),當(dāng)應(yīng)用程序退出時,調(diào)用用CloseHandle關(guān)閉設(shè)備。本文所述的系統(tǒng)是用DeviceIoControl和驅(qū)動程序通信。CreateFile打開設(shè)備的方式有兩種:符號鏈接名與GUID接口,本文所述驅(qū)動程序采用的是符號鏈接名的方式。
m_hDevice=CreateFile(sLinkName,...);//以符號鏈接名的方式打開設(shè)備
上述代碼中sLinkName為符號鏈接名,它與驅(qū)動程序中設(shè)置的符號鏈接名相同。m_hDevice為返回的設(shè)備的有效句柄,應(yīng)用程序就可以應(yīng)用它調(diào)用DeviceIoControl函數(shù)與驅(qū)動程序交換數(shù)據(jù)。應(yīng)用程序的請求會被放入請求隊列中,并在EvtIoDeviceControl函數(shù)之中被處理。
本文中應(yīng)用程序獲取時鐘卡上的時間信息的方式有兩種:(1)直接讀取。(2)中斷方式。
對于第一種方式,應(yīng)用程序直接調(diào)用DeviceIoControl函數(shù)與驅(qū)動程序交換數(shù)據(jù)。由于系統(tǒng)的雙口RAM被映射到虛擬內(nèi)存,驅(qū)動程序可以使用下面兩條指令對雙口RAM進(jìn)行讀寫: READ_REGISTER_XXX;//讀雙口RAM,WRITE_REGISTER_XXX;//寫雙口RAM。
對于中斷方式,當(dāng)被捕獲的外部事件發(fā)生時,驅(qū)動程序會進(jìn)入中斷服務(wù)例程EvtInterruptIsr,然后進(jìn)入延時過程調(diào)用EvtInterruptDpc,首先清中斷源,然后將雙口RAM中的時間數(shù)據(jù)讀取到設(shè)備上下文中緩存,該數(shù)據(jù)即為外部事件發(fā)生的時間,最后通知應(yīng)用程序讀取該數(shù)據(jù)。應(yīng)用程序?qū)⒄{(diào)用DeviceIoControl函數(shù)獲取設(shè)備上下文中的時間信息。驅(qū)動程序與應(yīng)用程序通信的方法有兩種:DeviceIoControl異步完成和WIN32事件通知。本文所述系統(tǒng)采用WIN32事件通知的方法。對于此種方法,應(yīng)用程序初始化時首先生成一個通知事件,并通過DeviceIoControl函數(shù)的輸入緩沖區(qū)發(fā)送給驅(qū)動程序,驅(qū)動程序創(chuàng)建相應(yīng)的內(nèi)核事件,同時使能PCI9052的LINT1中斷,當(dāng)該事件發(fā)生時,驅(qū)動程序會通知應(yīng)用程序,應(yīng)用程序的一個子線程不停的循環(huán)等待驅(qū)動程序發(fā)來的事件發(fā)生通知。當(dāng)設(shè)備被卸載時需要撤銷該內(nèi)核事件。具體主要代碼如下:
應(yīng)用程序生成通知事件:
mhEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
應(yīng)用程序子線程中等待事件發(fā)生:
while (WaitForSingleObject(mhEvent, 0) != WAIT_OBJECT_0)
{...}
驅(qū)動程序創(chuàng)建相應(yīng)的內(nèi)核事件:
ObReferenceObjectByHandle(....);
允許PCI中斷,使能PCI9052的本地LINT1中斷,pREG為PCI9052映射的I/O空間的基 地址:
inter = READ_PORT_USHORT(pREG + 0x4c);
inter |=0x43;
WRITE_PORT_USHORT(pREG + 0x4c, inter);
清中斷源,設(shè)置PCI9052的CS3引腳有效,通知CPLD清掉LINT1信號:
inter = READ_PORT_USHORT(pREG + 0x50);
inter |= 0x800;
WRITE_PORT_USHORT(pREG + 0x50, inter);
驅(qū)動程序給應(yīng)用程序發(fā)送事件,通知應(yīng)用程序讀取數(shù)據(jù):
KeSetEvent(pDevice_context->Event, 0, FALSE);
驅(qū)動程序內(nèi)撤銷內(nèi)核事件:
ObDereferenceObject(...);
3 結(jié)語
驅(qū)動程序是硬件與應(yīng)用程序通信的橋梁,它對系統(tǒng)性能提升的作用舉足輕重。高效、穩(wěn)定、可靠的驅(qū)動程序可以使系統(tǒng)性能得到很好的提升。
本文簡要介紹了PCI同步時鐘從卡的工作原理,并重點討論了基于WDF模型的PCI設(shè)備驅(qū)動程序設(shè)計方法。本文所述的PCI同步時鐘卡驅(qū)動程序,在WDK8.1中成功編譯,自動生成SYS文件(驅(qū)動程序代碼)和INF文件(設(shè)備安裝信息),成功安裝并且能夠穩(wěn)定可靠地運行。經(jīng)測試,捕獲的時間精度達(dá)到誤差小于200us,滿足系統(tǒng)設(shè)計要求。涉及本驅(qū)動程序的系統(tǒng)已應(yīng)用于三峽大壩左岸發(fā)電廠發(fā)變機(jī)組的故障錄波系統(tǒng)中,運行穩(wěn)定可靠。總而言之,WDF驅(qū)動模型優(yōu)化并簡化了設(shè)備驅(qū)動程序的開發(fā),比傳統(tǒng)的WDM驅(qū)動模型更加穩(wěn)定。
參考文獻(xiàn)
[1]武安河.Windows設(shè)備驅(qū)動程序WDF開發(fā)[M].北京:電子工業(yè)出版社,2009.
[2][美]Ronald D. Reeves 著,張猛等 譯.Windows設(shè)備驅(qū)動程序開發(fā)[M].北京:人民郵電出版社,2012.
[3]黎順杰,張艷榮.基于WDF的PCI-CAN設(shè)備驅(qū)動程序設(shè)計[J].電子測試,2013;5:20-21.
【關(guān)鍵詞】USB 設(shè)備驅(qū)動 Linux
1 USB總線原理
USB 協(xié)議是1994年底由康柏、IBM、英特爾等幾家公司聯(lián)合提出來的外部總線接口協(xié)議。USB就是英文中Universal Serial Bus(通用串行總線)的縮寫。USB總線具有其他總線所不具備的如:熱插拔、數(shù)據(jù)傳輸可靠、擴(kuò)展方便、成本低等一系列特點,因此在嵌入式系統(tǒng)中被廣泛使用。
一個USB系統(tǒng)一般是由一個USB主機(jī)控制器、一個或多個USB集線器和一個或多個USB設(shè)備節(jié)點組成。USB系統(tǒng)的物理連接具有層次性。USB總線連接USB設(shè)備和USB主機(jī),是一種星型拓?fù)浣Y(jié)構(gòu)。USB的拓?fù)浣Y(jié)構(gòu)如圖1所示。
在一個USB系統(tǒng)傳輸數(shù)據(jù)的過程中有兩個非常重要的概念,就是USB傳輸模式和USB描述符。USB傳輸模式是指USB設(shè)備傳輸數(shù)據(jù)的形式。USB設(shè)備支持四種傳輸模式:控制傳輸模式、同步傳輸模式、中斷傳輸模式和批量傳輸模式??刂苽鬏斈J绞怯脕硖幚鞺SB主端口到USB從端口的數(shù)據(jù)傳輸,主要是設(shè)備控制指令、設(shè)備查詢狀態(tài)指令和確認(rèn)指令。同步傳輸模式是指傳輸和時間關(guān)系密切的信息所使用的一種傳輸方式,是一種周期的、連續(xù)的單向傳輸方式。中斷傳輸模式這類傳輸模式主要用于傳輸非周期性的、自然發(fā)生的、數(shù)據(jù)量很小的信息,這類數(shù)據(jù)傳輸?shù)姆较蚴菑脑O(shè)備到主機(jī),適用于鍵盤、鼠標(biāo)、操縱桿等設(shè)備上。最后一種是批量傳輸模式,該模式適用于大量的、對時間沒有要求的數(shù)據(jù)傳輸,如U盤或者移動硬盤等設(shè)備。
USB設(shè)備在邏輯上分為幾個層次,分別是設(shè)備層(Device)、配置層(Config)、接口層(Interface)、端點層(Endpoint)。各個層次都有與之相對的描述符,分別是設(shè)備描述符、配置描述符、接口描述符和端點描述符。
2 Linux下的USB驅(qū)動框架
USB設(shè)備的設(shè)備描述符在Linux系統(tǒng)中用usb_device_descriptor結(jié)構(gòu)體表示,它描述了USB設(shè)備的一般信息。配置描述符用usb_config_descriptor結(jié)構(gòu)體表示,它給出了USB設(shè)備的配置信息。接口驅(qū)動程序是在一個配置內(nèi)給出一個接口信息,它在Linux中由usb_interface_descriptor結(jié)構(gòu)體表示。端口描述符被主機(jī)用來決定每個端口的帶寬需求,它在Linux系統(tǒng)中由usb_endpoint_descriptor結(jié)構(gòu)體表示。
編寫一個USB驅(qū)動程序,是從usb_driver結(jié)構(gòu)體開始的。Linux中模塊加載函數(shù)調(diào)用usb_register()和usb_unregister()從而對usb_driver結(jié)構(gòu)體進(jìn)行加載與卸載。如果某個設(shè)備信息與該驅(qū)動中usb_device_id usb_mouse_id_table 結(jié)構(gòu)體的信息相一致,則會調(diào)用usb_driver中探測成員函數(shù)probe(),將初始化USB斷點信息,并對設(shè)備做一些初始化工作,分配urb結(jié)構(gòu)體,準(zhǔn)備數(shù)據(jù)傳輸。其urb處理大致框架結(jié)構(gòu)如圖2所示。
當(dāng)鼠標(biāo)設(shè)備在用戶空間打開時,將提交 probe 函數(shù)構(gòu)建的 urb 請求塊,urb 將開始為傳送數(shù)據(jù)而忙碌了。urb 請求塊就像一個裝東西的“袋子”,USB 驅(qū)動程序把“空袋子”提交給 USB core,然后再交給主控制器,主控制器把數(shù)據(jù)放入這個“袋子”后再將裝滿數(shù)據(jù)的“袋子”通過 USB core 交還給 USB 驅(qū)動程序,這樣一次數(shù)據(jù)傳輸就完成了。
3 結(jié)束語
由于USB簡單方便快捷等優(yōu)點,許多外接設(shè)備會越來越青睞USB接口,這是一種發(fā)展的趨勢。Linux系統(tǒng)具有開源、安全等特性,用戶也在急劇增加。屆時,會有越來越多的USB驅(qū)動加入Linux內(nèi)核之中。
參考文獻(xiàn)
[1]Jonathan Corbet,Alessandro Rubini,Greg Kroah-Hartman等.LINUX設(shè)備驅(qū)動程序[M].北京:中國電力出版社,2006.
[2]Universal Serial Bus Specification Compaq,Intel,Mi―crosoft,NEC Revision 1.1.September 23,1998.
[3]溫卡特斯瓦蘭.精通Linux驅(qū)動程序開發(fā)[M].北京:人民郵電出版,2009.
[4]胡曉軍,張愛成.USB接口卡發(fā)技術(shù)[M].西安:西安電子科技大學(xué)出社,2005:15-17.
作者簡介
徐海林(1989-),男,江蘇省南通市人。現(xiàn)為安徽理工大學(xué)計算機(jī)科學(xué)與工程學(xué)院學(xué)生。
第一節(jié)windows nt網(wǎng)絡(luò)結(jié)構(gòu)
§1.1.1 windows nt網(wǎng)絡(luò)體系結(jié)構(gòu)
windows nt的網(wǎng)絡(luò)體系結(jié)構(gòu)是基于國際標(biāo)準(zhǔn)化(iso)制定的標(biāo)準(zhǔn)模型──開放式系統(tǒng)互連(open system interconnection:osi)參考模型分層建立的,這種方式有利于隨時擴(kuò)展其它功能和服務(wù)。
windows nt網(wǎng)絡(luò)模型開始于mac子層,網(wǎng)卡驅(qū)動程序就駐留在其中。它通過相關(guān)的網(wǎng)卡把windows nt與網(wǎng)絡(luò)連接起來,圖中的多個網(wǎng)卡表明在一臺運行windows nt的計算機(jī)上能使用多種網(wǎng)卡。
這一網(wǎng)絡(luò)體系結(jié)構(gòu)包括兩個重要接口──ndis接口與傳輸驅(qū)動
程序接口(tdi)。這兩個接口把兩個層隔離開來,辦法是相鄰的部件只允許按單一的標(biāo)準(zhǔn)來寫,不允許多重標(biāo)準(zhǔn)。例如一個網(wǎng)卡驅(qū)動程序(在ndis接口的下面)就不需要特地按每個傳輸協(xié)議來寫它的代碼塊,恰恰相反,該驅(qū)動程序是寫給ndis接口的,它通過符合ndis的相應(yīng)傳輸協(xié)議來請求服務(wù)。這些接口包含在windows nt的網(wǎng)絡(luò)體系結(jié)構(gòu)中,以容納可移植、可互換的模塊。
在兩個接口之間,是傳輸協(xié)議。它在網(wǎng)絡(luò)中起著組織者的作用。一個傳輸協(xié)議規(guī)定了數(shù)據(jù)以何種方式呈遞給下一個接收層,以及如何對數(shù)據(jù)相應(yīng)地進(jìn)行打包。它通過ndis把數(shù)據(jù)傳給網(wǎng)卡驅(qū)動程序,并通過tdi把數(shù)據(jù)傳給轉(zhuǎn)發(fā)程序(redirector)
tdi之上是轉(zhuǎn)發(fā)程序,它把本地的網(wǎng)絡(luò)資源申請轉(zhuǎn)送給網(wǎng)絡(luò)。
為了能和其他廠商的網(wǎng)絡(luò)互連,windows nt允許有多個轉(zhuǎn)發(fā)程序。對于每一個轉(zhuǎn)發(fā)程序windows nt計算機(jī)必須也有一個相應(yīng)的供應(yīng)者(provider)(由網(wǎng)絡(luò)廠商提供)。多供應(yīng)者路由選擇程序決定適當(dāng)?shù)墓?yīng)者,然后借助于供應(yīng)者,對應(yīng)用請求到相應(yīng)的轉(zhuǎn)發(fā)程序做出選擇。windows nt支持兩種類型的網(wǎng)絡(luò)驅(qū)動程序
傳輸驅(qū)動程序
實現(xiàn)數(shù)據(jù)鏈路層中的邏輯鏈路控制子層協(xié)議和傳輸層協(xié)議。向 下與ndis接口,向上與tdi接口。
網(wǎng)卡驅(qū)動程序
實現(xiàn)對物理層的管理和數(shù)據(jù)鏈路層中介質(zhì)訪問控制子層協(xié)議,通過ndis向下管理物理網(wǎng)卡,向上與傳輸驅(qū)動程序通信。
§1.1.3 windows nt網(wǎng)卡驅(qū)動程序
windows nt環(huán)境下的網(wǎng)卡驅(qū)動程序也分為兩種:
miniport網(wǎng)卡驅(qū)動程序:miniport驅(qū)動程序只須實現(xiàn)與網(wǎng)絡(luò)硬件相關(guān)的操作(包括發(fā)送和接收)。而所有底層網(wǎng)卡驅(qū)動程序的通用操作(如同步),一般由ndis接口程序來實現(xiàn)。
full網(wǎng)卡驅(qū)動程序:full網(wǎng)卡驅(qū)動程序必須實現(xiàn)所有硬件相關(guān)和同步、排隊等操作。例如full網(wǎng)卡驅(qū)動程序為了響應(yīng)數(shù)據(jù)接收,需要保持本身的捆綁信息,而miniport就可以由ndis接口庫來實現(xiàn)。
在windows nt的早期版本中,full網(wǎng)卡驅(qū)動程序要求開發(fā)者實現(xiàn)許多底層操作,來處理多處理器的核心問題以及處理器、線程的同步,這樣不同的開發(fā)者在大量重復(fù)著許多相同的工作。
而miniport網(wǎng)卡驅(qū)動程序允許開發(fā)者僅僅寫一些與網(wǎng)絡(luò)硬件相關(guān)的代碼即可,而那些通用的函數(shù)由ndis接口庫來實現(xiàn),這樣開發(fā)出來的驅(qū)動程序減少了不必要的工作。
第二節(jié)miniport驅(qū)動程序的結(jié)構(gòu)
ndis接口規(guī)范了網(wǎng)卡驅(qū)動程序的實現(xiàn),同時也對tdi驅(qū)動程序的實現(xiàn)提出了一定的要求,在nt中,ndis約束下的網(wǎng)卡驅(qū)動程序、tdi驅(qū)動程序和系統(tǒng)的關(guān)系如下圖所示:
圖2.0 ndis約束下的網(wǎng)卡驅(qū)動程序、tdi驅(qū)動程序和系統(tǒng)的關(guān)系
miniport驅(qū)動程序包括驅(qū)動程序?qū)ο?、?qū)動程序源代碼和ndis接口庫代碼。windows nt ddk提供ndis.h作為miniport驅(qū)動程序的主要頭文件,定義了miniport驅(qū)動程序的入口點、ndis接口庫函數(shù)和通用數(shù)據(jù)結(jié)構(gòu)。
上邊緣函數(shù)的作用是網(wǎng)卡驅(qū)動與ndis接口庫進(jìn)行通信,而下邊緣函數(shù)是tdi協(xié)議驅(qū)動程序與ndis通信的手段。ndis用一個叫做邏輯網(wǎng)卡的軟件對象來描述系統(tǒng)中的每塊網(wǎng)卡,而邏輯網(wǎng)卡與windows nt設(shè)備對象的通信由i/o子系統(tǒng)來管理,描述網(wǎng)卡的設(shè)備對象包括相關(guān)的網(wǎng)絡(luò)信息如名字、網(wǎng)絡(luò)地址和網(wǎng)卡內(nèi)存基地址等,它還包含與硬件相關(guān)的驅(qū)動程序狀態(tài)數(shù)據(jù)(捆綁數(shù)目,捆綁句柄,包過濾數(shù)據(jù)庫等)。ndis分配一個句柄到miniportinitialize這個上邊緣函數(shù)的一個結(jié)構(gòu)中,然后miniport網(wǎng)卡驅(qū)動程序?qū)⒃谝院筇峁┻@個句柄來給ndis調(diào)用,這個結(jié)構(gòu)一直被ndis保持,并且對miniport驅(qū)動程序不透明。 當(dāng)miniport網(wǎng)卡驅(qū)動程序初始化一塊網(wǎng)卡時,它創(chuàng)立自己的內(nèi)部數(shù)據(jù)結(jié)構(gòu)來描述網(wǎng)卡,記錄需要它管理的與設(shè)備相關(guān)的狀態(tài)信息。當(dāng)miniport網(wǎng)卡驅(qū)動程序調(diào)用ndismsetatttibutes或ndismsetattributesex兩ndis庫函數(shù)時,它傳遞一個句柄給這數(shù)據(jù)結(jié)構(gòu)。這樣,當(dāng)調(diào)用miniport驅(qū)動程序入口點時,它就傳遞這個句柄來驗證驅(qū)動程序所對應(yīng)的網(wǎng)卡的正確性。這個數(shù)據(jù)結(jié)構(gòu)為miniport網(wǎng)卡驅(qū)動程序所擁有并維護(hù)。miniport nic驅(qū)動程序還需要維護(hù)一組對象,這些對象是系統(tǒng)定義的對象標(biāo)識符(object idetifier:oid)來標(biāo)識,以描述驅(qū)動程序的性能和當(dāng)前狀態(tài)信息。為查詢這些信息,上層驅(qū)動程序調(diào)用ndisrequest向ndis接口庫指示oid。oid表示了調(diào)用所需的信息類型,如miniport驅(qū)動程序所支持的lookahead緩沖區(qū)大小等。ndis接到上層驅(qū)動程序的查詢請求,將oid傳遞給上邊緣函數(shù)miniportqueryinformation實現(xiàn)對oid的查詢,如果上層驅(qū)動程序請求改變狀態(tài)信息則調(diào)用miniportsetinformation實現(xiàn)對oid的設(shè)置。典型的miniport nic驅(qū)動程序必須有一些函數(shù)來通過ndis接口實現(xiàn)上層驅(qū)動程序與硬件的通信。這些函數(shù)稱為上邊緣服務(wù)函數(shù)。
這些上邊緣服務(wù)函數(shù)由驅(qū)動程序的開發(fā)者根據(jù)驅(qū)動程序面向的特定低層網(wǎng)絡(luò)類型和硬件以及相應(yīng)環(huán)境,可以有選擇地實現(xiàn),但必須保證驅(qū)動程序最基本的功能,這些基本功能包括初始化、發(fā)送、中斷處理、重置、參數(shù)查詢與設(shè)置和報文接收。
miniportinitialize:操作系統(tǒng)根據(jù)系統(tǒng)配置信息,檢測出網(wǎng)卡已安裝時,由ndis接口在初始化時調(diào)用,主要完成低層網(wǎng)絡(luò)類型確定,對應(yīng)于物理網(wǎng)卡的邏輯網(wǎng)卡初始化,中斷信息注冊,網(wǎng)卡與主機(jī)通訊方式的確認(rèn)。i/o端口的申請與注冊,內(nèi)存映像,mib的初始化,物理網(wǎng)卡的驗證與初始化等。
miniportreconfigure:支持網(wǎng)卡參數(shù)動態(tài)變化,和miniportinitilize一樣由ndis接口以初始化級別調(diào)度執(zhí)行(不能屏蔽中斷,必須由驅(qū)動程序承認(rèn)并清除在此期間產(chǎn)生的中斷),支持即插即用和軟配置的網(wǎng)卡在動態(tài)改變參數(shù)時,必須提供此函數(shù)。
miniportqueryinformation:查詢網(wǎng)卡的狀態(tài)以及網(wǎng)卡驅(qū)動程序的操作或統(tǒng)計參數(shù),如是否支持組通訊、網(wǎng)卡的物理速率是否支持回環(huán)、是否支持直接拷貝等,這些參數(shù)以oid方式統(tǒng)一管理。
miniportsetinformation:ndis接口或協(xié)議驅(qū)動程序通過調(diào)用此接口改變驅(qū)動程序維護(hù)的oid庫,一些操作參數(shù)的改變也將同時改變驅(qū)動程序狀態(tài),例如組地址的設(shè)置。
miniportreset:包括網(wǎng)卡硬件重置和驅(qū)動程序軟件重置,軟件重置包括驅(qū)動程序狀態(tài)重置,以及一些相關(guān)的參數(shù)重置,還需考慮有些參數(shù)的恢復(fù),重置時不必完成所有正在活躍的外部請求,但必須釋放已占用的外部資源。
miniporthalt:掛起網(wǎng)卡并釋放該網(wǎng)卡驅(qū)動程序占用的所有資源,在此期間不屏蔽中斷。
miniportisr:高優(yōu)先級的中斷處理程序,進(jìn)行的工作包括初始中斷處理類型,決定是否進(jìn)行中斷轉(zhuǎn)交,對卡上中斷進(jìn)行處理 等,該服務(wù)類型只在以下情況被調(diào)用:
ndis接口調(diào)用miniportinitialize和miniporthalt兩函數(shù)時。
.中斷處理類型設(shè)為每此中斷處理過程都調(diào)用時。
為使系統(tǒng)能及時響應(yīng)所有硬件中斷,高優(yōu)先級的硬件中斷處理程序應(yīng)盡可能的減少運行時間,防止長時間的屏蔽低優(yōu)先級中斷,避免造程中斷丟失。
miniporthandleinterrupt:由中斷延時處理程序在中斷延時處理時進(jìn)行調(diào)用。ndis排隊所有的延時處理,該服務(wù)主要處理發(fā)送完成、報文接收、描述符用盡、溢出、網(wǎng)卡異常等中斷。
miniportsend:ndis收到上層發(fā)送請求時經(jīng)過若干協(xié)議處理再向下調(diào)用此服務(wù)過程,發(fā)送的packet已含有l(wèi)lc和mac頭,該服務(wù)過程進(jìn)行邊界對齊、packet約束重整、描述符映射和報文發(fā)送、以及發(fā)送資源和packet緩沖隊列管理。
miniporttransferdata:多個已和網(wǎng)卡捆綁的協(xié)議驅(qū)動程序在接收到報文到達(dá)指示后,向網(wǎng)卡驅(qū)動程序發(fā)出傳送請求以拷貝各自所需的報文數(shù)據(jù)部分,網(wǎng)卡驅(qū)動程序根據(jù)各協(xié)議驅(qū)動程序?qū)蝹€packet是否進(jìn)行多次拷貝,以決定是否暫存只允許單次拷貝的packet等。
miniportcheckhandle:ndis每秒調(diào)用此服務(wù)函數(shù)一次,驅(qū)動程序發(fā)現(xiàn)網(wǎng)卡異常時報告給ndis由ndis調(diào)用miniportreset進(jìn)行硬件重恢復(fù)。
miniportenableintrrupt:中斷使能。
miniportdisableinterrupt:中斷屏蔽。
另外,每個網(wǎng)卡驅(qū)動程序必須有一個初始化入口點,由driver entry函數(shù)實現(xiàn),它和系統(tǒng)相關(guān),由操作系統(tǒng)在裝入驅(qū)動程序時調(diào)用,主要完成初始化ndis wrapper,再由wrapper初始生成驅(qū)動程序管理塊并完成相應(yīng)各種初始化工作,登錄網(wǎng)卡驅(qū)動程序所有上邊緣服務(wù)入口點,同時寫入ndis版本信息。ndis接口庫包括在ndis.sys中,它是一個核態(tài)函數(shù)庫,有一套抽象的函數(shù),無論協(xié)議驅(qū)動程序還是nic驅(qū)動程序都連接到這個庫中,以實現(xiàn)上下層之間的操作。
第二章fddi網(wǎng)卡驅(qū)動程序的加載和運行
第一節(jié) 網(wǎng)卡驅(qū)動程序的安裝
windows nt網(wǎng)卡驅(qū)動程序安裝的目的是實現(xiàn)網(wǎng)卡相應(yīng)硬件信息和驅(qū)動程序在windows nt注冊庫中的注冊,使windows nt能夠正確識別網(wǎng)卡,了解所必需的軟硬件信息并能在windows nt啟動時加載相應(yīng)驅(qū)動程序。
網(wǎng)卡驅(qū)動程序安裝時,首先在主群組的控制面板中選擇“網(wǎng)絡(luò)”,然后添加網(wǎng)卡,指定相應(yīng)信息文件──oemsetup.inf的路徑,以完成以下兩個必要的操作:
復(fù)制驅(qū)動程序到相應(yīng)的系統(tǒng)目錄(windows nt根目錄system32drivers)中;
在windows nt注冊庫中存入相應(yīng)軟硬件信息。
下面主要以fddi網(wǎng)卡為例介紹安裝驅(qū)動程序所必需的工作:
§2.1.1網(wǎng)卡一般硬件參數(shù)
對于fddi網(wǎng)卡,必須在編寫其oemsetup.inf文件時確定以下硬件參數(shù):
總線類型:pci(5)……括號中的數(shù)字5表示pci總線在ndis中的總線類型代碼;
廠商代號:0x5588……系統(tǒng)加載時確定網(wǎng)卡的標(biāo)記,也是編程時確定pci槽號的標(biāo)識;
cfid: 0x01;
介質(zhì)類型:光纖(3) ……括號中的數(shù)字表示光纖在ndis中的介質(zhì)類型代碼;
是否支持全雙工:支持。
對于其它的硬件信息在此inf配置信息文件中可有可無,如若配置,則可在驅(qū)動程序的編寫時利用這些信息,方便編程,同時有利于其它應(yīng)用對其參數(shù)的確定和使用。網(wǎng)卡驅(qū)動程序的安裝通常將創(chuàng)建登錄表中的四個不同子鍵:
software registrion鍵,對應(yīng)于驅(qū)動程序,存在于hkey_local_machinesoftwarecompany productnameversion中。我們的fddi網(wǎng)卡驅(qū)動程序所對應(yīng)的是hkey_local_machinesoftwarenet612yhfddiyhfddi1.0;
網(wǎng)卡的軟件登錄鍵,存在于hkey_local_machinesoftwaremicrosoft windows ntnt3.51networkcardsyhfddi1;
驅(qū)動程序的服務(wù)登錄鍵,存在于hkey_local_machinesystemcurrentcontrolsetservices
網(wǎng)卡的服務(wù)登錄鍵,存在于hkey_local_machinesystemcurrentcontrolsetservices
對于每一個網(wǎng)絡(luò)部件,一個名為netrules的特殊子鍵在鄰近的驅(qū)動程序或網(wǎng)卡登錄子鍵里創(chuàng)建,netrules標(biāo)識網(wǎng)絡(luò)部件為網(wǎng)絡(luò)整體的一部分。
fddi網(wǎng)卡驅(qū)動程序?qū)?yīng)的標(biāo)準(zhǔn)軟件登錄表項將出現(xiàn)在以下路徑:
hkey_local_machinesoftwarenet612yhfddiyhfddi1.0;
驅(qū)動程序?qū)?yīng)的標(biāo)準(zhǔn)項的值為:
description =yhfddi/pci adapter controller
install date =……
……
refcount =0x01
servicename =yhfddi
softwaretype =driver
title =yhfddi/pci adapter controller
而且在yhfddi驅(qū)動程序相關(guān)的netrules子鍵下,這些值項為:
bindable =yhfddi driver yhfddi adapter non exclusiver
bindform =“yhfddisys”yes no container
class = reg_multi_sz “yhfddi driver basic”
infname =oemnad1.inf
type =yhfddisys ndisdriver yhfddidriver
use =driver
yhfddi網(wǎng)卡在如下路徑的networkcards子鍵里介紹:
hkey_local_machinesoftwaremicrosoft
windows ntnt3.51networkcardsyhfddi1;
網(wǎng)卡的標(biāo)準(zhǔn)項包括以下這些值:
description =yhfddi/pci adapter controller
install date =……
manufacturer =net612
productname =yhfddi
servicename =yhfddi01
title =[01]yhfddi/pci adapter controller
§2.1.3編寫inf信息配置文件
gui inf描述語言被windows nt用以書寫系統(tǒng)所有部件的配置文件,當(dāng)然也可以用以書寫網(wǎng)絡(luò)系統(tǒng)各部件的配置文件,該配置文件描述了網(wǎng)絡(luò)部件安裝、配置、刪除的執(zhí)行過程。當(dāng)網(wǎng)絡(luò)部件進(jìn)行初始安裝或二次安裝(通常通過ncpa進(jìn)行)時,安裝程序讀取部件對應(yīng)的配置文件,進(jìn)行解釋執(zhí)行。gui inf描述語言由節(jié)、命令、邏輯操作、變量規(guī)范、流程控制以及一套調(diào)用dll或外部程序的機(jī)制組成,其中,節(jié)是配置文件的主體,節(jié)可分為install節(jié)(類似于函數(shù)),shell節(jié)(也類似于函數(shù),但可調(diào)用insall和shell節(jié)),detect節(jié)(不包含命令),一個配置文件一般由若干不同類型的節(jié)組成。驅(qū)動程序的開發(fā)者根據(jù)需要可以在配置文件中編寫相應(yīng)代碼,使得用戶和系統(tǒng)之間能進(jìn)行交互,并且由用戶決定一些配置參數(shù)。
nt網(wǎng)卡配置文件有其一套規(guī)范,驅(qū)動程序開發(fā)者必須按規(guī)范編寫配置文件,一般來說,一個配置文件至少應(yīng)該提供下面三個節(jié):
安裝入口點:[identify]shell節(jié)。該節(jié)主要功能是給出安裝部件的類型名,系統(tǒng)通過它識別該部件屬于哪一大類(display,mouse,scsi,network等)中的哪一類(網(wǎng)絡(luò)adapter,driver,transport,service,network和netprovidor),同時,還需要給出映像文件和配置文件所在的源介質(zhì)及標(biāo)識。
[returnoption]shell節(jié)。系統(tǒng)執(zhí)行安裝identify節(jié)后,執(zhí)行該節(jié)。它主要功能是檢查所需安裝的部件是否支持的硬件平臺和語言,并給出網(wǎng)卡名(有些配置文件支持多類網(wǎng)卡,此時必須讓用戶進(jìn)行選擇,并獲得選擇結(jié)果)。
[installoption]shell節(jié)。該節(jié)是配置文件得主體,也是上次安裝完后再次進(jìn)行配置、刪除、更新的入口點。主要功能是拷貝映像文件和配置文件,生成配置的各種選項,創(chuàng)建該部件在注冊庫中對應(yīng)的各種登錄子樹并更新重寫。
第二節(jié) 驅(qū)動程序的加載過程
§2.2.1 windows nt的啟動過程
關(guān)鍵詞:ACM競賽;程序設(shè)計;課程;教學(xué)改革
中圖分類號:TP3-4 文獻(xiàn)標(biāo)識碼:A 文章編號:1007-9599?。?012) 19-0000-02
1 引言
計算機(jī)軟件技術(shù)的發(fā)展日新月異,給高等院校相關(guān)專業(yè)的教學(xué)帶來了很大的挑戰(zhàn),為了更好地適應(yīng)不斷變化的社會就業(yè)需求,就必須在傳統(tǒng)的計算機(jī)專業(yè)教學(xué)模式的基礎(chǔ)上開辟出一條新路。
在這樣的背景下,樂山師范學(xué)院計算機(jī)科學(xué)學(xué)院早在2005年就開始開展校企合作辦學(xué),與企業(yè)聯(lián)合培養(yǎng)校企合作方向的學(xué)生,至今已是第八屆。相比普通班,校企合作教改班所開設(shè)的專業(yè)課程更符合于當(dāng)前計算機(jī)人才市場的需求,典型的特點就是注重對學(xué)生的專業(yè)技能尤其是程序設(shè)計和軟件開發(fā)能力的系統(tǒng)性培養(yǎng),嚴(yán)格按照軟件工程師的培養(yǎng)模式來開展相關(guān)的理論和實踐教學(xué)環(huán)節(jié),這在很大程度上改變了以往只注重專業(yè)理論教學(xué)的局限性。
在對近幾年教改學(xué)生的就業(yè)情況進(jìn)行分析以后,明確肯定了校企合作教學(xué)模式為我院本科人才培養(yǎng)體系的改革起到了決定性的促進(jìn)作用,學(xué)生的專業(yè)技能有了明顯的增強(qiáng),也大大提高了畢業(yè)生的就業(yè)率。
但與此同時也認(rèn)識到存在的一些問題:首先,傳統(tǒng)的以程序設(shè)計語言語法描述為主線的教學(xué)方式,以及模式化的實驗內(nèi)容,使教師在教學(xué)過程中容易將重點偏向理論,降低了對學(xué)生實踐能力的鍛煉和考核;其次,我們的軟件工程師主要是在教室和機(jī)房這樣的環(huán)境下培養(yǎng)出來的,缺乏真刀真槍的實踐鍛煉機(jī)會;最后,雖然校企合作人才培養(yǎng)方案的整體實施效果不錯,但也很難培養(yǎng)出高層次的計算機(jī)專業(yè)人才。
如果以上幾點不能有效地解決,那么校企合作辦學(xué)的成效和前景將受到限制,因此迫切地需要一種途徑去驅(qū)動程序設(shè)計類專業(yè)課程的教學(xué)模式改革,經(jīng)過長期、反復(fù)的思考和摸索,我們認(rèn)為通過開展學(xué)科專業(yè)競賽活動來推動課程教學(xué)改革是比較可行的。而在種類繁多的計算機(jī)學(xué)科專業(yè)競賽中,最權(quán)威、級別最高的就是《ACM/ICPC國際大學(xué)生程序設(shè)計競賽》。
本教改項目結(jié)合ACM競賽來促進(jìn)計算機(jī)專業(yè)教學(xué)體系特別是程序設(shè)計類課程的教學(xué)改革,教改實施對象主要為計算機(jī)科學(xué)學(xué)院軟件工程專業(yè)方向的學(xué)生。首先針對程序設(shè)計類課程教學(xué)存在的問題以及問題產(chǎn)生的原因進(jìn)行分析,然后在ACM競賽模式和特點的基礎(chǔ)上,嘗試通過結(jié)合ACM競賽來改革課程開設(shè)體系和課程教學(xué)模式,最后提出了解決問題的具體措施,并在實際教學(xué)應(yīng)用中取得了一定的成效。
2 當(dāng)前程序設(shè)計類課程教學(xué)存在的問題
2.1 人才培養(yǎng)模式陳舊,實踐教學(xué)比例不足
在傳統(tǒng)的被動教學(xué)模式中,學(xué)生缺乏學(xué)習(xí)主動性、創(chuàng)新性和行業(yè)競爭力。而計算機(jī)專業(yè)課程大多屬于實踐型課程,強(qiáng)調(diào)動手能力。為了加深對理論知識的理解,必須提高實踐教學(xué)質(zhì)量,理論和實踐教學(xué)的學(xué)時分配要作適當(dāng)調(diào)整。
2.2 實踐內(nèi)容模板化,缺乏創(chuàng)新能力的培養(yǎng)
首先,設(shè)計性、綜合性實驗偏少,很難培養(yǎng)學(xué)生的創(chuàng)造性思維;其次,實驗內(nèi)容嚴(yán)重脫離了現(xiàn)代軟件工程過程,更談不上對綜合型應(yīng)用問題的解決;最后,在實踐教學(xué)過程中,教師干預(yù)太多,學(xué)生處于被動完成實驗任務(wù)的角色。
2.3 缺乏互助學(xué)習(xí)能力,團(tuán)隊協(xié)作意識較差
當(dāng)前軟件項目的開發(fā)都是以團(tuán)隊形式實施的,團(tuán)隊成員之間需要合理分工和無障礙溝通。但在傳統(tǒng)教學(xué)模式中,以項目組為單位來開展教學(xué)活動的機(jī)會非常少,更談不上互助學(xué)習(xí)和團(tuán)隊協(xié)作了。
2.4 課程考核模式單一,缺乏激勵機(jī)制
課程考核主要采用傳統(tǒng)考核模式,考核內(nèi)容受限于教材知識點,缺乏對學(xué)生知識結(jié)構(gòu)與實踐技能的綜合考察,不利于學(xué)生綜合實踐能力和創(chuàng)新能力的培養(yǎng),最終形成“高分低能”的現(xiàn)象。
3 改革措施
本教改項目主要通過以下幾個方面來實施以ACM競賽促進(jìn)程序設(shè)計類課程教學(xué)改革的方案。
3.1 改革課程開設(shè)計劃
全面分析了目前程序設(shè)計類專業(yè)課程教學(xué)中存在的一些問題(比如教法和學(xué)法等方面),結(jié)合ACM的競賽大綱和競賽模式來調(diào)整開課計劃,把原計劃一學(xué)期的《程序設(shè)計基礎(chǔ)》課程的教學(xué)時間調(diào)整為一學(xué)年,第一學(xué)期是程序設(shè)計的入門教學(xué),主要介紹高級程序設(shè)計語言編程基礎(chǔ);第二學(xué)期是程序設(shè)計的進(jìn)階教學(xué),主要介紹算法設(shè)計與分析。
3.2 改革課程實踐教學(xué)模式[1]
(1)實驗內(nèi)容分級化:
將實驗內(nèi)容分成知識型(單一算法)、應(yīng)用型(算法和實際問題結(jié)合)和綜合型(若干小算法的綜合,用于解決一個較大規(guī)模的問題)。不同級別題型的權(quán)值不同,每一級別中又包含若干個相同權(quán)值的題目,學(xué)生可以根據(jù)自身情況選擇不同級別的題型和題目數(shù)量,這樣既考慮到了不同層次學(xué)生的學(xué)習(xí)需求,又達(dá)到了統(tǒng)一的實驗?zāi)康摹?/p>
(2)實驗題目趣味化:
傳統(tǒng)的程序設(shè)計類實驗題目普遍比較枯燥,難以調(diào)動學(xué)生的學(xué)習(xí)興趣和設(shè)計思路。參考ACM的海量題集,由任課教師將實驗題目生活化和趣味化,使學(xué)生自主選擇合理的數(shù)據(jù)結(jié)構(gòu)和算法來解題,這樣可以充分激發(fā)學(xué)生的學(xué)習(xí)主動性和積極性,將被動學(xué)習(xí)轉(zhuǎn)化為主動學(xué)習(xí),更好地達(dá)到了實踐教學(xué)的目的。
(3)實驗時間分散化:
考慮到實驗課時非常有限,可參照ACM競賽平臺來構(gòu)建“程序設(shè)計在線評測系統(tǒng)”,功能包括用戶管理、題庫管理、在線提交、在線排名、在線討論等。學(xué)生注冊后可在任何時間登陸該系統(tǒng)進(jìn)行選題、提交、評測和討論等自主學(xué)習(xí)環(huán)節(jié),將有限的課內(nèi)練習(xí)時間延續(xù)到課外。
3.3 開發(fā)資源網(wǎng)站
在全面搜集ACM競賽相關(guān)資源的前提下,以程序員協(xié)會的學(xué)生會員為主力設(shè)計并開發(fā)了“ACM資源網(wǎng)站”,并掛靠在學(xué)院的Web服務(wù)器上,以該資源網(wǎng)為平臺來開展競賽的宣傳、組織、培訓(xùn)等活動,同時也為相關(guān)課程的理論實踐教學(xué)和學(xué)生自主學(xué)習(xí)提供了一個優(yōu)質(zhì)的信息化平臺。
3.4 建設(shè)學(xué)生梯隊
依托于樂山師范學(xué)院第二課堂課程《ACM程序設(shè)計》的開設(shè),以樂山師范學(xué)院三星級社團(tuán)“程序員協(xié)會”為活動主體,在全校范圍內(nèi)吸納對計算機(jī)編程和競賽感興趣的學(xué)生,成立“ACM競賽興趣小組”,通過舉辦專業(yè)講座、學(xué)生科研、協(xié)會內(nèi)部競賽、協(xié)會沙龍等活動,為本專業(yè)學(xué)生提供一個進(jìn)一步增強(qiáng)職業(yè)技能的交流和學(xué)習(xí)平臺,同時也要在興趣小組中發(fā)現(xiàn)適合參加ACM競賽的后備人才,面向各年級構(gòu)建ACM競賽梯隊。
3.5 建立激勵機(jī)制
增設(shè)創(chuàng)新學(xué)分,設(shè)置創(chuàng)新環(huán)節(jié),搭建創(chuàng)新實踐的平臺,讓學(xué)生有更多的機(jī)會展示自己的專業(yè)特長。將參加ACM等學(xué)科競賽納入學(xué)生的綜合測評,通過設(shè)立競賽獎學(xué)金制度來引導(dǎo)學(xué)生積極參加課外科技活動、不斷提高自身的創(chuàng)新素質(zhì)。
3.6 組織參賽
在本教改項目的實施過程中,還要積極組織學(xué)生參加各個級別的ACM賽事。對于每一次競賽,首先成立競賽領(lǐng)導(dǎo)小組,分析官方公布的競賽大綱,及時、準(zhǔn)確地改革專業(yè)教學(xué)體系目標(biāo)和課程開設(shè)計劃;其次根據(jù)往屆參賽經(jīng)驗,結(jié)合本次競賽的具體情況制定出競賽活動方案,將競賽的宣傳、組織、選拔、培訓(xùn)、參賽、獎勵等環(huán)節(jié)制度化;然后選拔ACM參賽隊伍,指派經(jīng)驗豐富且取得過優(yōu)異成績的教練對參賽隊員進(jìn)行長期、深入、全方位的強(qiáng)化培訓(xùn)和指導(dǎo);最后通過對競賽成績的分析再次調(diào)整專業(yè)課程開設(shè)計劃和教學(xué)模式。[2]
3.7 改革考核手段
ACM模式的重要特色之一是完善而嚴(yán)謹(jǐn)?shù)目己藱C(jī)制,所以我們大膽嘗試將ACM的考核方式借鑒到程序設(shè)計類課程的考核環(huán)節(jié)中,采用ACM模式的黑箱測試,將學(xué)生在“程序設(shè)計在線評測系統(tǒng)”中獲得的成績以50%的權(quán)重加入到課程考核指標(biāo)當(dāng)中。這一方面減少了教師的工作量,降低了考核錯誤率,另一方面做到了客觀、公正,更好地發(fā)掘了學(xué)生的創(chuàng)新能力,提高其對知識點的掌握程度。
4 要解決的關(guān)鍵問題
4.1 課程教學(xué)形式的改革,特別是如何處理實踐教學(xué)和理論教學(xué)的比重關(guān)系,以及如何讓學(xué)生能夠真正地解決問題,而不是按照設(shè)定好的思路去模仿著解決問題。
4.2 課程評價體系的改革,尤其是目前的實踐環(huán)節(jié)評價機(jī)制弊端明顯,嚴(yán)重束縛了學(xué)生的創(chuàng)新能力,錯誤地引導(dǎo)學(xué)生把自己改造為一個受制于理論教材的傀儡。
4.3 差異化教學(xué),考慮到ACM競賽的難度較大,所以必須考慮到在將ACM融入到專業(yè)課程教學(xué)過程之后,如何確保整體教學(xué)質(zhì)量并解決好部分學(xué)生學(xué)習(xí)能力較差的問題。
4.4 在ACM競賽中取得更好的成績,必須建立有效的組織、選拔、培訓(xùn)、參賽、總結(jié)等相關(guān)機(jī)制。
5 結(jié)語
ACM競賽對程序設(shè)計類專業(yè)課程的教學(xué)改革起到了積極的推動作用,從教學(xué)隊伍建設(shè)的角度來看,它在提高教師的教學(xué)水平、科研能力、促進(jìn)專業(yè)的對外交流等方面都起到了重要的作用;從學(xué)生培養(yǎng)的角度來看,它在提高學(xué)生的學(xué)習(xí)興趣、自學(xué)能力、創(chuàng)新能力、求真務(wù)實的科學(xué)態(tài)度上有很大的幫助。
總之,通過合理的應(yīng)用ACM競賽這個平臺,可以使我們的計算機(jī)專業(yè)教學(xué)更趨科學(xué)化、規(guī)范化,可以讓我們的學(xué)生開拓視野,促進(jìn)實踐型、創(chuàng)新型人才的培養(yǎng),提高學(xué)生的就業(yè)競爭力。
參考文獻(xiàn):
[1]常子楠.基于ACM模式的程序設(shè)計類課程實踐教學(xué)探索[J].計算機(jī)教育,2010(16):144-146.
[2]項煒.以學(xué)科競賽促進(jìn)計算機(jī)專業(yè)教學(xué)改革的探索[J].改革與開放,2009(12):207.
[作者簡介]
為了保證操作系統(tǒng)的平安性和穩(wěn)定性以及應(yīng)用程序的可移植性,Windows操作系統(tǒng)不答應(yīng)應(yīng)用程序直接訪問系統(tǒng)的硬件資源,而是必須借助于相應(yīng)的設(shè)備驅(qū)動程序。設(shè)備驅(qū)動程序可以直接操作硬件,假如應(yīng)用程序和設(shè)備驅(qū)動程序之間實現(xiàn)了雙向通信,也就達(dá)到了應(yīng)用程序控制底層硬件設(shè)備的目的。它們之間的通信包括兩個方面摘要:一方面是應(yīng)用程序傳送給設(shè)備驅(qū)動程序的數(shù)據(jù);另一方面是設(shè)備驅(qū)動程序發(fā)送給應(yīng)用程序的消息。前者的實現(xiàn)較輕易,通過CreateFile()函數(shù)獲取設(shè)備驅(qū)動程序的句柄后,就可以使用Win32函數(shù),如DeviceIoControl()、ReadFile()或WriteFile()等實現(xiàn)應(yīng)用程序和設(shè)備驅(qū)動程序之間的通信。后者的實現(xiàn)遠(yuǎn)比前者復(fù)雜,同時介紹這方面情況的文章較少。這不等于說它不重要,相反,它在有些應(yīng)用場合發(fā)揮著重要的功能。設(shè)備驅(qū)動程序完成數(shù)據(jù)的采集工作后,需要馬上通知應(yīng)用程序,以便應(yīng)用程序能夠及時將數(shù)據(jù)取走并進(jìn)行處理。諸如此類情況,不一而足。
鑒于設(shè)備驅(qū)動程序通知應(yīng)用程序的重要性,本人結(jié)合一些經(jīng)驗,對它進(jìn)行了總結(jié),歸納出5種方法摘要:異步過程調(diào)用(APC)、事件方式(VxD)、消息方式、異步I/O方式和事件方式(WDM)。下面分別說明這幾種方式的原理,并給出實現(xiàn)的部分源代碼。
1 異步過程調(diào)用(APC)
Win32應(yīng)用程序使用CreateFile()函數(shù)動態(tài)加載設(shè)備驅(qū)動程序,然后定義一個回調(diào)函數(shù)backFunc(),并且將回調(diào)函數(shù)的地址%26amp;backFunc()作為參數(shù),通過DeviceIoControl()傳送給設(shè)備驅(qū)動程序。設(shè)備驅(qū)動程序獲得回調(diào)函數(shù)的地址后,將它保存在一個全局變量(如callback)中,同時調(diào)用Get_Cur_Thread_Handle()函數(shù)獲取它的應(yīng)用程序線程的句柄,并且將該句柄保存在一個全局變量(如appthread)中。當(dāng)條件成熟時,設(shè)備驅(qū)動程序調(diào)用_VWIN32_QueueUserApc()函數(shù),向Win32應(yīng)用程序發(fā)送消息。這個函數(shù)帶有三個參數(shù)摘要:第一個參數(shù)為回調(diào)函數(shù)的地址(已經(jīng)注冊);第二個參數(shù)為傳遞給回調(diào)函數(shù)的消息;第三個參數(shù)為調(diào)用者的線程句柄(已經(jīng)注冊)。Win32應(yīng)用程序收到消息后,自動調(diào)用回調(diào)函數(shù)(實際是由設(shè)備驅(qū)動程序調(diào)用)?;卣{(diào)函數(shù)的輸入?yún)?shù)是由設(shè)備驅(qū)動程序填入的,回調(diào)函數(shù)在這里主要是對消息進(jìn)行處理。
2 事件方式(VxD)
首先,Win32應(yīng)用程序創(chuàng)建一個事件的句柄,稱其為Ring3句柄。由于虛擬設(shè)備驅(qū)動程序使用事件的Ring0句柄,因此,需要創(chuàng)建Ring0句柄。用LoadLibrary()函數(shù)加載未公開的動態(tài)鏈接庫Kernel32.dll,獲得動態(tài)鏈接庫的句柄。然后,調(diào)用GetProcAddress(), 找到函數(shù)OpenVxDHandle()在動態(tài)鏈接庫中的位置。接著,用OpenVxDHandle()函數(shù)將Ring3事件句柄轉(zhuǎn)化為Ring0事件句柄。Win32應(yīng)用程序用CreateFile()函數(shù)加載設(shè)備驅(qū)動程序。假如加載成功,則調(diào)用DeviceIoControl()函數(shù)將Ring0事件句柄傳給VxD;同時,創(chuàng)建一個輔助線程等待信號變成有信號狀態(tài),本身則可去干其它的事情。當(dāng)條件成熟時,VxD置Ring0事件為有信號狀態(tài)(調(diào)用_VWIN32_SetWin32Event()函數(shù)),這馬上觸發(fā)對應(yīng)的Ring3事件為有信號狀態(tài)。一旦Ring3事件句柄為有信號狀態(tài),Win32應(yīng)用程序的輔助線程就對這個消息進(jìn)行相應(yīng)的處理。
3 消息方式
Win32應(yīng)用程序調(diào)用CreateFile()函數(shù)動態(tài)加載虛擬設(shè)備驅(qū)動程序。加載成功后,通過調(diào)用DeviceIoControl()函數(shù)將窗體句柄傳送給VxD,VxD利用這個句柄向窗體發(fā)消息。當(dāng)條件滿足時,VxD調(diào)用SHELL_PostMessage()函數(shù)向Win32應(yīng)用程序發(fā)送消息。要讓該函數(shù)使用成功,必須用#define來自定義一個消息,并且也要照樣在應(yīng)用程序中定義它;還要在消息循環(huán)中使用ON_MESSAGE()來定義消息對應(yīng)的消息處理函數(shù),以便消息產(chǎn)生時,能夠調(diào)用消息處理函數(shù)。SHELL_PostMessage()函數(shù)的第一個參數(shù)為Win32窗體句柄,第二個參數(shù)為消息ID號,第三、四個參數(shù)為發(fā)送給消息處理函數(shù)的參數(shù),第五、六個參數(shù)為回調(diào)函數(shù)和傳給它的參數(shù)。Win32應(yīng)用程序收到消息后,對消息進(jìn)行處理。
4 異步I/O方式
Win32應(yīng)用程序首先調(diào)用CreateFile()函數(shù)加載設(shè)備驅(qū)動程序。在調(diào)用該函數(shù)時,將倒數(shù)第2個參數(shù)設(shè)置為FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,表示以后可以對文件進(jìn)行重疊I/O操作。當(dāng)設(shè)備驅(qū)動程序文件創(chuàng)建成功后,創(chuàng)建一個初始態(tài)為無信號、需要手動復(fù)位的事件,并且將這個事件傳給類型為OVERLAPPED的數(shù)據(jù)結(jié)構(gòu)(如Overlapped)。然后,將Overlapped作為一個參數(shù),傳給DeviceIoControl()函數(shù)。設(shè)備驅(qū)動程序把這個I/O請求包(IRP)設(shè)置為掛起狀態(tài),并且設(shè)置一個取消例程。假如當(dāng)前IRP隊列為空,則將這個IRP傳送給StartIo()例程;否則,將它放到IRP隊列中。設(shè)備驅(qū)動程序做完這些工作后,結(jié)束這個DeviceIoControl()的處理,于是Win32應(yīng)用程序可能不等待IRP處理完,就從DeviceIoControl()的調(diào)用中返回。通過判定返回值,得到IRP的處理情況。假如當(dāng)前IRP處于掛起狀態(tài),則主程序先做一些其它的工作,然后調(diào)用WaitForSingleObject()或WaitForMultipleObject()函數(shù)等待Overlapped中的事件成為有信號狀態(tài)。設(shè)備驅(qū)動程序在適當(dāng)?shù)臅r候處理排隊的IRP,處理完成后,調(diào)用IoCompleteRequest()函數(shù)。該函數(shù)將Overlapped中的事件設(shè)置為有信號狀態(tài)。Win32應(yīng)用程序?qū)@個事件馬上進(jìn)行響應(yīng),退出等待狀態(tài),并且將事件復(fù)位為無信號狀態(tài),然后調(diào)用GetOverlappedResult()
函數(shù)獲取IRP的處理結(jié)果。
5 事件方式(WDM)
Win32應(yīng)用程序首先創(chuàng)建一個事件,然后將該事件句柄傳給設(shè)備驅(qū)動程序,接著創(chuàng)建一個輔助線程,等待事件的有信號狀態(tài),自己則接著干其它事情。設(shè)備驅(qū)動程序獲得該事件的句柄后,將它轉(zhuǎn)換成能夠使用的事件指針,并且把它寄存起來,以便后面使用。當(dāng)條件具備后,設(shè)備驅(qū)動程序?qū)⑹录O(shè)置為有信號狀態(tài),這樣應(yīng)用程序的輔助線程馬上知道這個消息,于是進(jìn)行相應(yīng)的處理。當(dāng)設(shè)備驅(qū)動程序不再使用這個事件時,應(yīng)該解除該事件的指針。
6 結(jié)語
在目前流行的Windows操作系統(tǒng)中,設(shè)備驅(qū)動程序是操縱硬件的最底層軟件接口。它向上提供和硬件無關(guān)的用戶接口,向下直接進(jìn)行I/O、硬件中斷、DMA和內(nèi)存訪問等操作。它將應(yīng)用程序和硬件細(xì)節(jié)屏蔽開來,使軟件不依靠于硬件并且可在多個不同的平臺之間移植。本文介紹了5種設(shè)備驅(qū)動程序通知應(yīng)用程序的方法,其中前3種方法主要用于VxD中,后2種方法主要用于WDM。這5種方法都經(jīng)過實際測試。測試結(jié)果表明,它們都能夠達(dá)到設(shè)備驅(qū)動程序通知應(yīng)用程序的目的。
參考文獻(xiàn)摘要:
[1歐青立,徐建波,李方敏,等. 虛擬設(shè)備驅(qū)動程序VxD的探究和開發(fā). 計算機(jī)工程,2003