單體強,陳 雷,張萬發(fā)
(軍械工程學院 彈藥工程系,河北 石家莊 050003)
隨著現(xiàn)代測控系統(tǒng)自動化水平的不斷提高,在大型測控系統(tǒng)的軟件設計過程中,經(jīng)常會遇到需要多個任務同時工作的情況。若采用傳統(tǒng)的單線程編程方法,軟件系統(tǒng)的執(zhí)行效率低,系統(tǒng)可靠性差;而多線程技術(shù)特別適用于實時多任務系統(tǒng)[1],采用多線程技術(shù),則可以把這些任務分配給多個線程同時執(zhí)行,在一段時間內(nèi)并行完成多個任務,提高了軟件的執(zhí)行效率和系統(tǒng)可靠性。LabWindows/CVI是NI公司提供的一種ANSI C集成開發(fā)環(huán)境[2],其將多線程技術(shù)引入虛擬儀器軟件設計中,有效利用OS和CPU,縮短響應時間、避免擁塞出現(xiàn),使系統(tǒng)整體性能得到大幅提高。
進程通常被定義為應用程序的運行實例。在Win32中,每個進程擁有4 GB的地址空間,此外還有別的資源,如文件、動態(tài)內(nèi)存分配和線程[3]。這些資源在進程中被創(chuàng)建,當進程終止時被釋放。
線程是進程內(nèi)部可獨立執(zhí)行單元,是操作系統(tǒng)對系統(tǒng)資源的基本調(diào)度單位。多線程是指操作系統(tǒng)支持一個進程中執(zhí)行多個線程的能力。應用程序中的每個進程都擁有一個主線程和零到多個次線程。同屬于一個進程的線程共享進程的虛擬地址空間,線程之間可共享進程的全局數(shù)據(jù)和資源。此外,每個線程都單獨保存一些數(shù)據(jù)結(jié)構(gòu)、CPU寄存器指針和堆棧,以保存線程和執(zhí)行環(huán)境。進程與線程之間的資源分布關(guān)系如圖1所示。
圖1 進程與線程之間資源分布關(guān)系圖Fig.1 Relation chart of thread and process resources
LabWindows/CVI提供兩種次線程運行代碼的高級機制,分別是線程池 (thread pools)和異步定時器(asynchronous timers)。線程池適用于需要不連續(xù)地執(zhí)行或在循環(huán)中執(zhí)行的任務,而異步定時器適用于在固定時間間隔內(nèi)執(zhí)行的任務[4]。
線程在線程池中創(chuàng)建和管理,線程池在主線程中創(chuàng)建。當喚出次線程的控件得到響應時,則在線程池中創(chuàng)建一個次線程,線程函數(shù)就通過占用Windows的時間片開始運行,而不再需要程序流程的干預,直到主動或被動停止為止。線程池中對多線程的管理包括創(chuàng)建線程池、創(chuàng)建線程、運行線程函數(shù)、釋放線程池資源等。
線程池的運行需要調(diào)用Utility Library中的Cmt Schedule Thread Pool Function函數(shù),把在次線程中執(zhí)行的函數(shù)名傳遞給它,使其在線程池的一個次線程中運行。調(diào)用Cmt Waitfor Schedule Thread P-ool Function Completion函數(shù)使主線程在結(jié)束之前處于等待狀態(tài),直到線程函數(shù)完成執(zhí)行。如果主線程在次線程完成執(zhí)行之前退出,則次線程可能沒有機會完全釋放其占用的資源,次線程中用到的庫函數(shù)也可能沒有機會完全釋放。在多線程程序中,調(diào)用函數(shù)Cmt Release Thread Pool Function ID和函數(shù)Cmt Terminate Thread Pool Thread均可退出線程,但是后者無法保證安全退出線程,處理不當有可能導致無法工作。調(diào)用函數(shù)Cmt New Thread Pool可以創(chuàng)建一個新的線程池,Cmt New Thread Pool會返回線程池的句柄(pool Handle),并把它傳遞給函數(shù)CmtSchedule Thread Pool Function的第一個參數(shù)。通過Cmt New Thread Pool創(chuàng)建的線程池,在該線程結(jié)束時,必須調(diào)用Cmt Discard Thread Pool函數(shù)釋放該線程池的資源。
同步定時器執(zhí)行線程的優(yōu)先級比較低[5],當程序線程在別處停滯或響應用戶界面操作時,其發(fā)送的定時消息會受到消息隊列和系統(tǒng)時鐘頻率等因素的影響,使定時消息得不到及時的響應和處理,這給基于定時功能的重要操作的編程帶來極大的不利。異步定時器利用Windows多媒體定時器在指定的時間間隔點調(diào)用執(zhí)行函數(shù),異步定時的時間間隔精確,可對設備進行軟件定時。與同步定時器相比,異步定時器使用獨立線程,與程序主線程無關(guān),能夠提供可靠的定時精度,有效避免了由于程序主線程或用戶界面操作而產(chǎn)生的延時,確保了定時器事件的實時性。異步定時器本質(zhì)上是多線程技術(shù)的一種應用形式。
基于LabWindows/CVI,利用同步定時器實現(xiàn)單線程工作模式,如圖2所示,利用異步定時器實現(xiàn)多線程工作模式,如圖3所示,以此比較兩者的軟件執(zhí)行效率和系統(tǒng)可靠性。單線程模式下,在定時器控件的回調(diào)函數(shù)中產(chǎn)生數(shù)據(jù)并在第一個繪圖控件上繪出曲線。多線程模式下,利用異步時鐘產(chǎn)生一個次線程,并在這個線程中產(chǎn)生數(shù)據(jù),同時在主線程的定時器控件的回調(diào)函數(shù)中顯示數(shù)據(jù)。第二個繪圖控件用來直觀反映定時器控件每次執(zhí)行代碼所需的時間。在單線程工作模式下,若進行其他界面操作,那么顯示數(shù)據(jù)操作被推遲,顯示的數(shù)據(jù)失真,時間間隔大大超過了所界定的200 ms。在多線程工作模式下,因為顯示數(shù)據(jù)和產(chǎn)生數(shù)據(jù)分屬兩個不同的線程,所以其它界面操作并未影響數(shù)據(jù)處理與波形顯示產(chǎn)生。這說明多線程在提高軟件執(zhí)行效率和系統(tǒng)可靠性等方面均優(yōu)于單線程。
圖2 單線程工作模式Fig.2 Single threading modle
圖3 多線程工作模式Fig.3 Multithreading modle
數(shù)據(jù)保護是使用多線程技術(shù)時必須解決的一個關(guān)鍵問題,保護全局變量、靜態(tài)局部變量和動態(tài)分配的變量,避免它們被多個線程同時訪問時造成邏輯錯誤。 Lab Windows/CVI提供了3種線程同步數(shù)據(jù)保護機制:線程鎖(thread lock)、線程安全變量 (thread safe variables)和線程安全隊列(thread safe queues)[6]。線程鎖與線程安全變量數(shù)據(jù)保護機制是線程同步中對資源的互斥使用;線程安全隊列數(shù)據(jù)保護機制是線程同步中兩個以上線程基于某個條件來協(xié)調(diào)它們的活動,一個線程的執(zhí)行依賴于另一個協(xié)作線程的消息或信號,當一個線程沒有得到來自另一個線程的消息或信號時則需等待,直到消息或信號到達才被喚醒。
在線程鎖數(shù)據(jù)保護機制中,數(shù)據(jù)保護是通過將保存數(shù)據(jù)的變量和OS中的線程鎖對象進行關(guān)聯(lián)來實現(xiàn)的。在一個特定的時間內(nèi),OS只允許一個線程獲得特定的線程鎖對象。程序利用CmtNewLock函數(shù)建立線程鎖;利用CmtGetLock函數(shù)使指定線程獲得線程鎖控制權(quán)。每一個時刻只能有一個線程獲得線程鎖,且每次調(diào)用此函數(shù)后必須調(diào)用CmtReleaseLock函數(shù)釋放線程鎖控制權(quán)。若程序中使用的線程占有線程鎖較長時間,可能導致其它想獲得線程鎖的線程不得不等待較長時間,降低了程序的可執(zhí)行性,容易出現(xiàn)阻塞甚至死鎖,效率較低。
線程安全變量把數(shù)據(jù)和OS中的線程鎖定對象組合成為一個整體。因為只需要傳遞線程安全變量句柄,而不是傳遞線程鎖句柄和被保護的變量,所以被保護數(shù)據(jù)更容易在函數(shù)間傳遞。第一次訪問線程安全變量需調(diào)用Initialize Var Name函數(shù),在程序中止前調(diào)用Uninitialize Var Name函數(shù),調(diào)用Cet Pointer To Var Name函數(shù)來獨占該變量,可以進行線程安全變量的訪問。訪問結(jié)束后,調(diào)用Release Pointer To Var Name函數(shù)放棄對該變量的占有權(quán),以便其它線程訪問該變量。
線程安全隊列是線程間安全傳輸數(shù)組的一種機制,是為多個線程之間傳遞大批量數(shù)據(jù)提供的一種數(shù)據(jù)保護措施。線程安全隊列內(nèi)部采用了鎖策略,有效避免了線程間的沖突、數(shù)據(jù)錯誤、死鎖等情況的出現(xiàn)。調(diào)用Cmt New TSQ函數(shù)可以實現(xiàn)線程安全隊列的建立。在調(diào)用該函數(shù)時,根據(jù)線程間傳送數(shù)據(jù)信息量多少,指定線程安全隊列的項目數(shù)和每一項目的大小。寫線程調(diào)用函數(shù)Cmt Write TSQ Data將一定數(shù)量的數(shù)據(jù)信息寫入到線程安全隊列中,而讀線程調(diào)用函數(shù)Cmt Read TSQ Data從安全隊列中讀取指定數(shù)量的數(shù)據(jù)信息。
某武器系統(tǒng)中所涉及的需進行測控的資源達二十多種。所有測控資源的初始化都是在啟動測控程序時完成的,所有測控資源的關(guān)閉是在退出程序時完成的。因此,若用單線程初始化/關(guān)閉所有的測控資源會導致程序啟動/退出時間過長,降低了軟件執(zhí)行效率和系統(tǒng)可靠性。據(jù)此,在設計啟動/退出程序時,采用了Lab Windows/CVI多線程技術(shù)。限于篇幅,只給出測控程序的啟動流程圖,如圖4所示。
程序啟動后開始執(zhí)行主線程,主線程啟動兩個次線程來初始化儀器。當次線程初始化儀器完畢后,置該次線程的標志變量為1,然后調(diào)用函數(shù)Set Sleep Policy,使其處于休眠狀態(tài)。在退出程序時,再啟動這兩個次線程關(guān)閉測控資源。主線程用于處理用戶界面事件,若用戶界面上的“取消”控件被按下,則應立即終止測控資源的初始化,退出測控程序。如果用單線程編寫測控程序,當出現(xiàn)突發(fā)故障需立即終止程序執(zhí)行時,按下“終止”控件,有時會發(fā)現(xiàn)程序不能立即響應用戶界面事件,可能由此造成嚴重后果。采用多線程技術(shù)可以很好的解決此問題。在“啟動”控件按下時,系統(tǒng)創(chuàng)建一個新的線程用于自動測控過程,而主線程用于處理用戶界面事件,這樣在需要緊急終止測試程序時,可以保證事件響應的實時性。當主線程接到終止命令時,調(diào)用Cmt Terminate Thread Pool Thread函數(shù)結(jié)束次線程函數(shù)的執(zhí)行,并調(diào)用函數(shù)Cmt Release Thread Pool Function ID釋放線程函數(shù)資源,提高了測控系統(tǒng)的可靠性。
圖4 測控程序啟動過程流程圖Fig.4 Flow chart of the software startup
深入研究了Lab Windows/CVI多線程技術(shù)的運行機制及其數(shù)據(jù)保護機制,通過分析和實際應用表明,該技術(shù)提高了操作系統(tǒng)的執(zhí)行效率和系統(tǒng)的可靠性,在改善系統(tǒng)實時性和最大程度利用多處理器的性能上具有明顯的優(yōu)勢,對測控技術(shù)的發(fā)展具有重要的作用。
[1]張毅剛.虛擬儀器軟件開發(fā)環(huán)境Labwindows/CVI編程指南[M].北京:機械工業(yè)出版社,2002.
[2]陳矯陽,陳楸.基于LabWindows/CVI多線程數(shù)據(jù)采集的研究[J].科學技術(shù)與工程,2008,8(9):2459-2461.CHEN Jiao-yang,CHEN Qiu.Study of multithread data acquiring on the base of LabWindows/CVI[J].Science Technology and Engineering,2008,8(9):2459-2461.
[3]成鳳敏,蘇小光.多線程技術(shù)在虛擬儀器軟件開發(fā)中的應用[J].中國測試技術(shù),2008,34(2):48-50.CHENG Feng-min,SU Xiao-guang.Application of multithreading in virtual instrument software development[J].China Measurement Technology,2008,34(2):48-50.
[4]楊東升,王高峰.多線程技術(shù)在虛擬儀器開發(fā)軟件LabWindows/CVI中的實現(xiàn)[J].電測與儀表,2005,42(471):39-54.YANG Dong-sheng,WANG Gao-feng.Application of multithreading based on virtual instrument software Lab Windows/CVI[J].Electrical Measurement&Instrumentation,2005,42(471):39-54.
[5]姜守達,吳昌盛,孫震.LabWindows/CVI多線程機制在數(shù)據(jù)采集中的應用[J].計算機應用,2004,23(8):56-63.JIANG Shou-da,WU Chang-sheng,SUN Zhen.Application of multithreading in data acquisition based on LabWindows/CVI[J].Computer Application,2004,23(8):56-63.
[6]馬青亮,周倫彬,鮑芳.LabWindows/CVI多線程機制在虛擬數(shù)字存儲示波器中的應用[J].中國測試技術(shù),2007,34(1):60-62.MA Qing-liang,ZHOU Lun-bin,BAO Fang.Application of Labwindows/CVI multithreading technology in virtual DSO[J].China Measurement Technology,2007,34(1):60-62.