摘要:提出了一種面向小型工業(yè)監(jiān)控軟件的實(shí)時(shí)數(shù)據(jù)庫(kù)解決方案。在Visual C++6.0編程環(huán)境下,采用ADO技術(shù)與多線程技術(shù)解決數(shù)據(jù)實(shí)時(shí)存儲(chǔ)與處理的問(wèn)題,并以法國(guó)施耐德公司的Modbus現(xiàn)場(chǎng)總線設(shè)備對(duì)試驗(yàn)平臺(tái)進(jìn)行試驗(yàn)運(yùn)行,其性能穩(wěn)定、運(yùn)行可靠。
關(guān)鍵詞:實(shí)時(shí)數(shù)據(jù)庫(kù); 監(jiān)控軟件; ADO; 多線程
中圖法分類號(hào):TP311.13文獻(xiàn)標(biāo)識(shí)碼:A
文章編號(hào):1001-3695(2006)09-0198-03
目前,隨著計(jì)算機(jī)技術(shù)、通信技術(shù)及現(xiàn)場(chǎng)總線技術(shù)的快速發(fā)展,企業(yè)為了提高生產(chǎn)效率和降低生產(chǎn)成本,增強(qiáng)企業(yè)的安全運(yùn)行系數(shù),廣泛地使用了計(jì)算機(jī)技術(shù)、現(xiàn)場(chǎng)總線技術(shù)對(duì)工業(yè)生產(chǎn)進(jìn)行改造和優(yōu)化。在一些不太復(fù)雜且相對(duì)較小的工業(yè)系統(tǒng)中,采用大型工業(yè)組態(tài)軟件與大型的實(shí)時(shí)數(shù)據(jù)庫(kù)系統(tǒng),將導(dǎo)致工程成本大幅提高。面對(duì)這一問(wèn)題,我們提出一種面向小型工業(yè)監(jiān)控軟件的實(shí)時(shí)數(shù)據(jù)庫(kù)解決方案。隨著Windows系統(tǒng)的普遍使用,很多計(jì)算機(jī)控制系統(tǒng)的上位機(jī)大多使用的是Windows操作系統(tǒng),采用Windows編程。VisualC++是Microsoft公司推出的面向?qū)ο蟮能浖_(kāi)發(fā)工具,其功能強(qiáng)大,集成的MFC類庫(kù)、ATL模板類以及AppWizard、ClassWizard等一系列的Wizard工具,可以很快地建立應(yīng)用程序,大大簡(jiǎn)化了應(yīng)用程序的設(shè)計(jì)過(guò)程。VisualC++還提供了多種數(shù)據(jù)庫(kù)訪問(wèn)技術(shù),如ODBCAPI,MFCODBC,DAO,OLEDB,ADO等。
1設(shè)計(jì)方案
1.1所涉及的技術(shù)簡(jiǎn)介
在這一方案中我們所采用的技術(shù)主要有Microsoft公司開(kāi)發(fā)的數(shù)據(jù)庫(kù)應(yīng)用程序的新接口ADO(ActiveDataObject)技術(shù);另外還采用了VisualC++6.0的多線程編程技術(shù),用來(lái)解決數(shù)據(jù)庫(kù)的多事務(wù)調(diào)度與并發(fā)處理問(wèn)題。
(1)ADO技術(shù)簡(jiǎn)介
ADO技術(shù)是建立在OLEDB之上的高層數(shù)據(jù)庫(kù)訪問(wèn)技術(shù)。它基于COM(ComponentObjectModel),具有COM組件的諸多優(yōu)點(diǎn),可以用來(lái)構(gòu)造可復(fù)用應(yīng)用框架,支持多語(yǔ)言,能夠訪問(wèn)關(guān)系數(shù)據(jù)庫(kù)、非關(guān)系數(shù)據(jù)庫(kù)及所有的文件系統(tǒng)。另外還具有遠(yuǎn)程數(shù)據(jù)服務(wù)(RemoteDataService,RDS)的特性。ADO的對(duì)象模型簡(jiǎn)化了對(duì)對(duì)象的操作,大大簡(jiǎn)化了程序編制,增加了程序的可移植性。多數(shù)情況下,我們只需要關(guān)心所要?jiǎng)?chuàng)建和使用的對(duì)象,而無(wú)須了解其父對(duì)象。在ADO中可以直接打開(kāi)一個(gè)記錄對(duì)象,而無(wú)須建立與數(shù)據(jù)源的連接。
ADO技術(shù)的特點(diǎn)如下:
①易于使用。由于ADO是高層應(yīng)用,具有面向?qū)ο蟮奶匦裕槐叵冉⑦B接,只需直接構(gòu)造即可。
②高速訪問(wèn)數(shù)據(jù)源。ADO技術(shù)基于OLEDB,所以它也繼承了OLEDB訪問(wèn)數(shù)據(jù)庫(kù)的高速性。
③可以訪問(wèn)不同的數(shù)據(jù)源。ADO技術(shù)可以訪問(wèn)關(guān)系數(shù)據(jù)庫(kù)和非關(guān)系數(shù)據(jù)庫(kù)的所有文件系統(tǒng)。
④可以用于MicrosoftActiveX頁(yè)。ADO技術(shù)可以以ActiveX控件的形式出現(xiàn),也可以用于MicrosoftActiveX頁(yè),簡(jiǎn)化了Web頁(yè)的編程。
⑤程序占用內(nèi)存少。由于ADO技術(shù)是基于組件對(duì)象模型(COM)的訪問(wèn)技術(shù),所以ADO產(chǎn)生的應(yīng)用程序占用內(nèi)存少。(2)多線程技術(shù)
多任務(wù)管理是操作系統(tǒng)的精華。所謂多任務(wù)就是有多個(gè)工作同時(shí)運(yùn)行。但CPU只有一個(gè),因此就采用分時(shí)多任務(wù)的方式。每個(gè)任務(wù)只運(yùn)行一小段時(shí)間,通過(guò)操作系統(tǒng)的調(diào)度機(jī)制來(lái)決定下一個(gè)CPU的使用權(quán)應(yīng)該交給哪一個(gè)任務(wù)。目前所說(shuō)的多任務(wù)大都是指多線程(MultiThreads)的方式。多數(shù)支持多線程的操作系統(tǒng)一般均支持五種線程狀態(tài),即睡眠狀態(tài)(Dormant)、準(zhǔn)備運(yùn)行狀態(tài)(Ready)、運(yùn)行狀態(tài)(Running)、等待狀態(tài)(Waiting)和延時(shí)狀態(tài)(Delayed)。圖1描述了這些狀態(tài)之間互相切換的情形。
Windows2000操作系統(tǒng)支持兩種類型的多任務(wù),即基于進(jìn)程(Process)的多任務(wù)和基于線程(Thread)的多任務(wù)。我們所采用的是基于線程的多任務(wù),每個(gè)線程均有自己的堆棧和CPU寄存器,其執(zhí)行由系統(tǒng)根據(jù)優(yōu)先級(jí)來(lái)調(diào)度執(zhí)行。基于線程的多任務(wù)允許同一個(gè)程序的兩個(gè)或多個(gè)部分同時(shí)執(zhí)行,這樣增加了程序的維數(shù),提高了程序的執(zhí)行效率。另外采用線程同步技術(shù),防止了兩個(gè)或多個(gè)任務(wù)同時(shí)操作數(shù)據(jù)而引起的錯(cuò)誤。
1.2方案
我們所采用的試驗(yàn)平臺(tái)為法國(guó)施耐德公司的Modbus現(xiàn)場(chǎng)總線設(shè)備;下位采用的是Quantum系列的CPU與其他智能板卡,通過(guò)以太網(wǎng)模塊與上位監(jiān)控機(jī)相連;上位采用VisualC++6.0與SQLServer2000為開(kāi)發(fā)工具,在Windows2000環(huán)境下開(kāi)發(fā)監(jiān)控軟件與實(shí)時(shí)數(shù)據(jù)庫(kù)。
當(dāng)下位的PLC板卡采集到數(shù)據(jù)后,先放入下位的CPU寄存器中,通過(guò)Modbus+TCP/IP協(xié)議將數(shù)據(jù)發(fā)送至上位監(jiān)控軟件并放入設(shè)計(jì)的緩存中,上位監(jiān)控軟件與SQLServer數(shù)據(jù)庫(kù)相連,采用ADO技術(shù)、多線程技術(shù),以及設(shè)置定時(shí)器,達(dá)到對(duì)數(shù)據(jù)的實(shí)時(shí)存儲(chǔ)與處理。其結(jié)構(gòu)如圖2所示。
2技術(shù)實(shí)現(xiàn)
在VisualC++6.0中實(shí)現(xiàn)上面的實(shí)時(shí)數(shù)據(jù)庫(kù)方案,主要有四個(gè)方面:①初始化ADO庫(kù)環(huán)境;②創(chuàng)建數(shù)據(jù)庫(kù)操作線程;③設(shè)置ADO對(duì)象智能指針;④利用定時(shí)器與ADO指針對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作。
2.1初始化ADO庫(kù)環(huán)境
(1)引入ADO庫(kù)文件
使用ADO技術(shù)前必須在工程的Stdafx.h文件最后用直接引入符號(hào)#import引入ADO庫(kù)文件,使編譯器能正確編譯。其代碼如下:
#import\"C:ProgramFilescommonfilessystemadomsado15.dll\"
No_namespace
rename(\"EOF\",\"adoEOF\")
ADO類的定義作為一種資源存儲(chǔ)在ADODLL(Msado15.dll)中,在其內(nèi)部稱為類型庫(kù)。
(2)生成應(yīng)用程序框架并初始化OLE/COM庫(kù)環(huán)境
在使用ADO技術(shù)的InitInstance函數(shù)中初始化OLE/COM庫(kù)(因?yàn)锳DO庫(kù)是一個(gè)COMDLL庫(kù))。
BOOLCAdotestDlg::OnInitDialog()
{
::CoInitialize(NULL);//初始化OLE/COM庫(kù)環(huán)境
}
程序最后要調(diào)用::CoUninitialize();//釋放程序占用的COM資源
另外:m_pRecordset>Close();
m_pConnection>Close();
m_pRecordset=NULL;
m_pConnection=NULL;
用于釋放所占用的ADO對(duì)象資源。
2.2創(chuàng)建數(shù)據(jù)庫(kù)操作線程
首先在VisualC++MFC中創(chuàng)立基于WinThread數(shù)據(jù)庫(kù)操作線程CProcessDataThread;
然后調(diào)用線程創(chuàng)建函數(shù)Create ̄Thread來(lái)創(chuàng)建數(shù)據(jù)庫(kù)線程;最后在程序結(jié)束時(shí)調(diào)用ExitThread函數(shù)終止線程,釋放資源。函數(shù)調(diào)用方法可以參考MicrosoftMSDN;另外還需注意的是,在多個(gè)線程同時(shí)運(yùn)行時(shí),若是執(zhí)行線程切換,就會(huì)有危險(xiǎn)發(fā)生,因此安排一種臨界區(qū)(CriticalSection),當(dāng)線程進(jìn)入臨界區(qū)時(shí),不運(yùn)行調(diào)度程序,以防止因調(diào)度機(jī)制而造成無(wú)法預(yù)期的后果。還有線程同步與多個(gè)線程之間如何溝通的問(wèn)題。解決這個(gè)問(wèn)題時(shí),采用信號(hào)(Semaphore)或者是事件(Event)的方式,設(shè)置全局變量(GlobalVariable)來(lái)控制線程之間的同步。
2.3ADO智能指針的設(shè)置與操作
(1)設(shè)置ADO智能指針
ADO庫(kù)包含三個(gè)基本接口:_ConnectionPtr接口、_CommandPtr接口和_RecordsetPtr接口。在庫(kù)環(huán)境初始化完成后,需要在頭文件中定義智能指針變量:
_ConnectionPtrm_pConnection;
_RecordsetPtrm_pRecordset;
_CommandPtrm_pCommand;
(2)智能指針對(duì)數(shù)據(jù)庫(kù)的操作
_ConnectionPtr接口返回一個(gè)記錄集或一個(gè)空指針。通常使用它來(lái)創(chuàng)建一個(gè)數(shù)據(jù)連接或執(zhí)行一條不返回任何結(jié)果的SQL語(yǔ)句,如一個(gè)存儲(chǔ)過(guò)程。使用_ConnectionPtr接口返回一個(gè)記錄集不是一個(gè)好的使用方法,對(duì)于要返回記錄的操作通常用_RecordsetPtr來(lái)實(shí)現(xiàn);用_ConnectionPtr操作時(shí)需要得到記錄條數(shù)遍歷所有記錄,而用_RecordsetPtr時(shí)不需要。
_CommandPtr接口返回一個(gè)記錄集。它提供了一種簡(jiǎn)單的方法來(lái)執(zhí)行返回記錄集的存儲(chǔ)過(guò)程和SQL語(yǔ)句。在使用_CommandPtr接口時(shí),你可以利用全局_ConnectionPtr接口,也可以在_CommandPtr接口里直接使用連接串。如果你只執(zhí)行一次或幾次數(shù)據(jù)訪問(wèn)操作,那么后者是比較好的選擇。但如果你要頻繁訪問(wèn)數(shù)據(jù)庫(kù),并要返回很多記錄集,那么你應(yīng)該使用全局_ConnectionPtr接口創(chuàng)建一個(gè)數(shù)據(jù)連接,然后使用_CommandPtr接口執(zhí)行存儲(chǔ)過(guò)程和SQL語(yǔ)句。
_RecordsetPtr是一個(gè)記錄集對(duì)象。與以上兩種對(duì)象相比,它對(duì)記錄集提供了更多的控制功能,如記錄鎖定、游標(biāo)控制等。與_CommandPtr接口一樣,它不一定要使用一個(gè)已經(jīng)創(chuàng)建的數(shù)據(jù)連接,還可以用一個(gè)連接串代替連接指針賦給_RecordsetPtr的Connection成員變量,讓它自己創(chuàng)建數(shù)據(jù)連接。如果要使用多個(gè)記錄集,最好的方法是與Command對(duì)象一樣使用已經(jīng)創(chuàng)建了數(shù)據(jù)連接的全局_ConnectionPtr接口,然后使用_RecordsetPtr執(zhí)行存儲(chǔ)過(guò)程和SQL語(yǔ)句。
2.4設(shè)置定時(shí)器以達(dá)到實(shí)時(shí)處理數(shù)據(jù)
為了實(shí)現(xiàn)數(shù)據(jù)的實(shí)時(shí)存儲(chǔ)功能,我們需要在程序中設(shè)置定時(shí)器,設(shè)置數(shù)據(jù)采樣頻率,實(shí)時(shí)地存儲(chǔ)數(shù)據(jù)。為了實(shí)現(xiàn)這一功能,我們需要調(diào)用WindowsAPI(應(yīng)用程序接口)函數(shù)中的定時(shí)器函數(shù)。CWnd::SetTimer()設(shè)置一個(gè)或多個(gè)定時(shí)器用于指定時(shí)間間隔觸發(fā)。其具體步驟是:先調(diào)用SetTimer(),參數(shù)值使用一個(gè)計(jì)時(shí)器ID和一個(gè)超時(shí)值,然后將WM_TIMER消息映射到應(yīng)用程序類的一個(gè)OnTimer()函數(shù)中。不再使用定時(shí)器后,調(diào)用KillTimer()來(lái)取消定時(shí)。
在該實(shí)時(shí)數(shù)據(jù)庫(kù)方案中這一部分是核心部分,部分代碼如下:
(1)設(shè)置定時(shí)器
SetTimer(2,2000,NULL);
//設(shè)定數(shù)據(jù)采樣時(shí)間為2s(根據(jù)實(shí)際要求設(shè)定)
(2)編寫(xiě)OnTimer函數(shù)
voidCMasterDlg::OnTimer(UINTnIDEvent)
{
this>UpdateData(1);
CStringY0;
Y0.Format(\"關(guān)\");
…
if(nIDEvent==2)
{
m_pRecordset>AddNew();
GetLocalTime(tm);
Time.Format(\"%d/%d%d:%d:%d\",tm.wMonth,tm.wDay,tm.wHour,tm.wMinute,tm.wSecond);
m_pRecordset>PutCollect(\"Time\",_variant_t(Time));
if(Coil[11]==1)
{
Y0.Format(\"開(kāi)\");
m_pRecordset>PutCollect(\"Y0\",_variant_t(Y0));
}
else
…
m_pRecordset>Update();
}
CDialog::OnTimer(nIDEvent);
}
顯示界面如圖3所示。
圖3顯示界面
3小結(jié)
通過(guò)實(shí)驗(yàn)我們驗(yàn)證了方案的可行性。在面向小型系統(tǒng)的基礎(chǔ)上,對(duì)數(shù)據(jù)存儲(chǔ)與處理的實(shí)時(shí)性方面滿足了設(shè)計(jì)的基本要求。但是在某些方面還需要進(jìn)一步的研究與實(shí)驗(yàn),如進(jìn)一步提高實(shí)時(shí)性及改進(jìn)數(shù)據(jù)庫(kù)與監(jiān)控軟件的接口,達(dá)到可擴(kuò)展與可移植;進(jìn)一步提高數(shù)據(jù)處理能力,實(shí)現(xiàn)動(dòng)態(tài)曲線、報(bào)警顯示等功能。
參考文獻(xiàn):
[1]劉懷,胡繼峰.實(shí)時(shí)系統(tǒng)的多任務(wù)調(diào)度[J].計(jì)算機(jī)工程,2002,28(3):4344.
[2]王日宏.基于VC的Win32多線程同步問(wèn)題[J].計(jì)算機(jī)系統(tǒng)應(yīng)用,2004,(7):6062.
[3]Sang H Son.Real-time Database Systems:Present and Future[C].Proceedings of IEEE Real- time Computing Systems and Applications,the 2nd International Workshop,1995.50-52.
[4]Lars Bkgaard,Jens Christian Godskesen.Real-time Event Control in Active Databases[J].The Journal of Systems and Software,1998,42(3):263-271.
作者簡(jiǎn)介:
郝曉弘(1960),男,甘肅平?jīng)鋈耍袊?guó)人工智能學(xué)會(huì)理事,中國(guó)人工智能學(xué)會(huì)理事分布式智能專業(yè)委員會(huì)委員,教授,博導(dǎo),主要研究方向?yàn)閺?fù)雜系統(tǒng)的控制、智能控制理論與應(yīng)用、計(jì)算機(jī)網(wǎng)絡(luò)與計(jì)算機(jī)控制技術(shù)、現(xiàn)場(chǎng)總線與現(xiàn)場(chǎng)控制網(wǎng)絡(luò);
李應(yīng)啟(1980),男,陜西西安人,碩士研究生,主要研究方向?yàn)殡娏﹄娮优c電力傳動(dòng)、現(xiàn)場(chǎng)總線與現(xiàn)場(chǎng)控制網(wǎng)絡(luò);
劉樹(shù)博(1982),男,吉林通化人,碩士研究生,主要研究方向?yàn)殡娏﹄娮优c電力傳動(dòng)等。