付笑宇 張線媚
摘 要:WinIo 3.0軟件包只提供了在C#使用WinIo的用例,且沒有提供WinIo.lib文件,使得VC 2010下無法直接使用WinIo。在VC 2010下對WinIo 3.0的源碼重新進行編譯生成WinIo.lib,修改WinIo.h文件后VC 2010下即可直接使用WinIo。給出了一個應用樣例,實驗結果表明該方法安全、簡潔、高效。
關鍵詞:內核態(tài) WDF 驅動程序 I/O端口
中圖分類號:TP311 文獻標志碼:A 文章編號:1672-3791(2015)05(a)-0020-02
在電網(wǎng)實時測控系統(tǒng)研發(fā)過程中,需要使用in和out指令對測控單元的端口直接進行讀寫,但X86CPU的硬件保護機制將I/O指令指定為特權指令,禁止用戶態(tài)的應用程序訪問I/O端口。用戶態(tài)的應用程序只能通過運行于核心態(tài)的設備驅動程序提供的API間接地訪問I/O端口,實時性較差。
Windows操作系統(tǒng)為用戶提供了WDM (Windows Driver Model)[1]架構,用于編寫設備驅動程序。WDM架構異常復雜,要求開發(fā)人員對Windows系統(tǒng)內部的管理機制非常熟悉,有豐富的系統(tǒng)級應用開發(fā)的經(jīng)驗,驅動程序的調試相對困難,其安全性與效率無法保障。
Yariv Kaplan在2010年發(fā)布開源軟件WinIo 3.0[2],它采用了非文檔化的Windows API(native API)和其它一些底層編程技巧繞過Windows安全保護機制,Windows下的應用程序程序可直接對I/O端口進行操作、
1 WinIo 3.0簡介
WinIo 3.0支持32位和64位版的Windows 7/8,它提供了10個庫函數(shù),用于對I/O端口和內存物理存儲單元的直接讀寫。WinIo軟件包由WinIo.sys、winio_nt.h、Winio.h、WinIo.dll、WinIo.lib(未提供,需要用戶在VC2010下生成)等5個核心文件組成。與I/O端口操作相關的4個函數(shù)如下:
(1)WinIo庫函數(shù)初始化。
WINIO_API bool -stdcall InitializeWinIo();
(2)卸載WinIo庫函數(shù)。
WINIO_API void -stdcall ShutdownWinIo();
(3)I/O端口讀操作函數(shù)。
WINIO_API bool _stdcall GetPortVal(WORD wPortAddr,PDWORD pdwPortVal,BYTE bSize);
參數(shù)wPortAddr為端口地址,16位整型變量或常量;參數(shù)pdwPortVal為指向一存放讀取端口內容的32位整型變量指針;參數(shù)bSize為實際讀取的字節(jié)數(shù),8位整型變量或常量,取值范圍為1、2或4,表示讀操作的對象為8位、16位或32位端口。
(4)I/O端口寫操作函數(shù)。
WINIO_API bool _stdcall SetPortVal(WORD wPortAddr,DWORD dwPortVal, BYTE bSize);
參數(shù)wPortAddr為端口地址,16位位整型變量或常量;參數(shù)dwPortVal為要寫入端口的32位整型變量或常量;參數(shù)bSize為實際寫出的字節(jié)數(shù),取值范圍為1、2或4,表示寫操作的對象為8位、16位或32位端口。
2 VC 2010下WinIo 3.0的應用
2.1 VC 2010下WinIo.lib的生成
WinIo 3.0軟件包的Source文件夾下包含了WinIo的源文件及其所需的資源,其下的DLL文件夾為VC 2010的WinIo項目文件夾。生成WinIo.lib文件的步驟如下。
(1)雙擊“WinIo.sln”啟動WinIo項目。
(2)在VC 2010 IDE下打開“生成”菜單,單擊“生成WinIo”。
生成的WinIo.lib文件它存放于“.\Suorce\DLL\Debug”文件夾。注意:VC 2010學習版不能生成WinIo.lib文件。
2.2 VC 2010下WinIo應用環(huán)境配置
(1)創(chuàng)建一個Win32控制臺應用項目。
啟動VC 2010,創(chuàng)建一個“Win32控制臺應用程序”的WinIoDemo項目,在VC2010 IDE下打開“生成”菜單,單擊“生成WinIoDemo”。
(2)復制WinIo核心文件到制定的文件夾。
將WinIo 3.0軟件包的Source文件夾下的winio_nt.h、Winio.h與WinIo.lib復制到WinIoDemo項目文件夾下,WinIo.sys與WinIo.dll復制到WinIoDemo項目文件夾下的Debug文件夾。
(3)修改Winio.h文件。
將Winio.h中的“#include"..\drv\winio_nt.h"”,修改為“#include "winio_nt.h"”;
(4)配置鏈接器附加依賴項。
在VC 2010 IDE下打開“項目”菜單,單擊“屬性”,打開項目屬性頁對話框,打開“配置屬性”目錄樹,選擇“鏈接器”下的“輸入”子項,在“附加依賴項”中添加“WinIo.lib”,如圖1所示。WinIo應用環(huán)境配置完成,用戶可以編寫自己的源代碼進行調試。
2.3 CMOS RAM讀寫實例
PC機的主板上集成有CMOS實時時鐘,為操作系統(tǒng)提供時間信息:年、月、日與時、分、秒。它附有128或256個字節(jié)的RAM,用于存放時間與硬盤、內存、顯示卡等最基本的硬件配置信息。操作系統(tǒng)啟動時,從CMOS實時時鐘中讀取時間信息作為系統(tǒng)的基準時間。系統(tǒng)斷電后由后備的鋰電池供電,以保障信息不丟失。
PC機為CMOS實時時鐘分配了70H和71H兩個8端口,用于訪問CMOS RAM,在進行讀寫操作時,需要先向70H端口寫入CMOS RAM單元的地址,然后通過71H端口進行讀寫操作。
CMOS RAM的0、2、4單元分別存放秒、分、小時信息,7、8、9單元依次存放日、月、年信息,這些數(shù)據(jù)均采用壓縮的BCD碼表示。下面的代碼是一個完整的利用WinIo實現(xiàn)對I/O端口直接進行讀寫操作的樣例,它先讀取CMOS RAM的9號單元的年份信息并顯示,然后再向9號單元寫入新的年份信息。重新啟動PC后,Windows系統(tǒng)則采用新的年份。該樣例源代碼在32位版的Windows 7/8操作系統(tǒng)平臺上,使用VC 2010調試通過。
#include "stdafx.h"
#include "stdio.h"
#include "conio.h"
#include
#include "winio.h"
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwPortVal;
bool bResult;
bResult = InitializeWinIo();
if (bResult)
{
// write CMOS ram addr=9
SetPortVal(0x70, 9, 1);
// read CMOS ram addr=9,year,BCD code
GetPortVal(0x71, &dwPortVal, 1);
printf("Current Year:%4x\n",dwPortVal);
printf("Enter new year:");
scanf("%x",&dwPortVal);
SetPortVal(0x70, 9, 1);
SetPortVal(0x71,dwPortVal , 1); //write new year
SetPortVal(0x70, 9, 1);
GetPortVal(0x71, &dwPortVal, 1); //read new year
printf(" new Year:%4x\n",dwPortVal);
// When you're done using WinIo, call ShutdownWinIo
ShutdownWinIo();
}
else
{
printf("Error during initialization of WinIo.\n");
exit(1);
}
printf("\nPress anyke to continue …");
_getch();
return 0;
}
3 結語
該文給出了一種在VC 2010下使用WinIo 3.0的簡潔方法,已有的采用使用WinIo 2.0開發(fā)的應用系統(tǒng),無需修改源代碼,在VC 2010下重新編譯后即可遷移到安全性更好的WinIo 3.0平臺。在實時測控系統(tǒng)的開發(fā)中,使用WinIo 3.0,省去了設備驅動程序的開發(fā)環(huán)節(jié),可以極大的縮短系統(tǒng)的開發(fā)周期,降低開發(fā)成本,系統(tǒng)的安全性和可靠性也得到了保障。
參考文獻
[1] 邰銘 ,武安河,于洪濤.Windows 2000/XP WDM設備驅動程序開發(fā)[M].北京:電子工業(yè)出版社,2003.
[2] Yariv Kaplan.WinIo[DB/OL].http://www.internals.com,2014-11-02.
[3] 孫穎.隨機波浪數(shù)據(jù)采集與處理技術的研究[D].天津:天津理工大學,2014.
[4] 萬振凱,郭建民.大型自動化三維編織復合材料編織機的開發(fā)[J].紡織導報,2013(9):64-66,68.
[5] 袁軍,譚永東,任俊.利用WinIo實現(xiàn)并口數(shù)據(jù)通信[J].計算機與現(xiàn)代化,2009(8):49-53.
[6] 馮曉偉,李正生,吳寧.XP系統(tǒng)下CB對ISA總線的讀寫方法及應用研究[J].自動化與儀器儀表,2011(5):17-19.
[7] 王元強,朱為.一種通過PCI總線配置FPGA的設計方法[J].現(xiàn)代電子技術,2010(2):90-92,95.