趙靜,張寧寧
(中航工業(yè)北京長(zhǎng)城計(jì)量測(cè)試技術(shù)研究所,北京100095)
在構(gòu)建自動(dòng)化控制系統(tǒng)時(shí),計(jì)算機(jī)軟件編程是使得自動(dòng)控制系統(tǒng)在無(wú)人參與情況下按照預(yù)期程序進(jìn)行工作的關(guān)鍵所在。在預(yù)定程序的實(shí)現(xiàn)中,軟件編程不僅要實(shí)現(xiàn)所需的任務(wù)要求,而且在運(yùn)行效率、差錯(cuò)管理、系統(tǒng)維護(hù)等方面要付出更多的精力。由于無(wú)人工參與,某些想象不到的小錯(cuò)誤可能會(huì)引起軟件的崩潰,進(jìn)而嚴(yán)重威脅整個(gè)控制系統(tǒng)。
隨著自動(dòng)控制系統(tǒng)的不斷擴(kuò)展,所需要實(shí)現(xiàn)的功能越來(lái)越多,系統(tǒng)越來(lái)越龐大,軟件編程越來(lái)越復(fù)雜,然而計(jì)算機(jī)的內(nèi)存資源是有限的,內(nèi)存管理的目的就是如何高效、快速的為任務(wù)分配內(nèi)存資源,并且在適當(dāng)?shù)臅r(shí)候釋放和回收資源,內(nèi)存管理技術(shù)在編程中越來(lái)越受到重視。一個(gè)內(nèi)存管理好的程序不僅可以提高工作效率,而且可以使系統(tǒng)更為穩(wěn)定的運(yùn)行,內(nèi)存管理不好可能導(dǎo)致內(nèi)存泄露,甚至內(nèi)存耗盡而導(dǎo)致系統(tǒng)崩潰。
本文基于LabVIEW編程語(yǔ)言來(lái)介紹內(nèi)存管理,通過(guò)匯總LabVIEW的一些內(nèi)存管理技術(shù)以及一些編程技巧,以幫助LabVIEW編程者更好的實(shí)現(xiàn)自動(dòng)控制系統(tǒng)的軟件編程。
自動(dòng)控制系統(tǒng)一般包括控制器、被控對(duì)象以及執(zhí)行機(jī)構(gòu)??刂破骷从?jì)算機(jī)及其內(nèi)置板卡;被控對(duì)象即終端設(shè)備;執(zhí)行機(jī)構(gòu)即實(shí)現(xiàn)基本控制任務(wù)、數(shù)據(jù)采集任務(wù)等的硬件結(jié)構(gòu),如電機(jī)、電磁閥、數(shù)據(jù)采集儀等。圖1是一個(gè)簡(jiǎn)單的自動(dòng)控制系統(tǒng)的基本構(gòu)架。
圖1 自動(dòng)控制系統(tǒng)框圖
系統(tǒng)中的控制部分往往需要用到計(jì)算機(jī)的各種硬件資源口:串口、網(wǎng)口、GPIB口等,或者需要多功能采集卡的多功能通道來(lái)進(jìn)行控制,這些系統(tǒng)資源端口在進(jìn)行軟件編程時(shí)要注意及時(shí)的分配和釋放,如果釋放不當(dāng),會(huì)導(dǎo)致資源口的無(wú)效占用,可能導(dǎo)致再次使用時(shí)打開失敗。
系統(tǒng)本身具有自檢功能,這是在整個(gè)程序控制中首先要進(jìn)行的工作,之后又不再需要進(jìn)行頻繁操作,這就涉及到了系統(tǒng)資源的合理分配問(wèn)題,如何使不常用的功能最少的占用內(nèi)存資源,并能更好的提高運(yùn)行效率。
在某些復(fù)雜系統(tǒng)中,數(shù)據(jù)量很大,占用的內(nèi)存資源也會(huì)很大,如何在編程中注意內(nèi)存資源的管理是提高數(shù)據(jù)處理量、提高運(yùn)行效率的關(guān)鍵。
此外,系統(tǒng)還包括了實(shí)時(shí)采集數(shù)據(jù)、人機(jī)控制、報(bào)表操作等多個(gè)功能,合理的內(nèi)存管理機(jī)制可以提高計(jì)算機(jī)多任務(wù)處理中的內(nèi)存利用率,保證系統(tǒng)運(yùn)行的穩(wěn)定性和提高系統(tǒng)的運(yùn)行效率。
2.1.1 內(nèi)存使用的查看工具
在VI屬性面板中的“內(nèi)存使用”工具是用來(lái)查看VI內(nèi)存占用情況的。它顯示了一個(gè)VI內(nèi)存占用所包含的四個(gè)主要部分:前面板、框圖、代碼和數(shù)據(jù),以及四個(gè)部分的總和。通過(guò)這個(gè)工具,我們可以方便的查看VI所占用的內(nèi)存,更有針對(duì)性的進(jìn)行優(yōu)化。
2.1.2 查看數(shù)據(jù)的內(nèi)存?zhèn)浞?/p>
通過(guò)本工具可以方便的找到產(chǎn)生內(nèi)存拷貝的數(shù)據(jù)節(jié)點(diǎn),更便于進(jìn)行程序的優(yōu)化設(shè)計(jì),對(duì)某些不必要的內(nèi)存拷貝,要盡量避免。此外,工具選項(xiàng)下的性能分析有幾個(gè)查看工具,靈活運(yùn)用這些工具可以更方便的進(jìn)行內(nèi)存管理。
當(dāng)打開一個(gè)主VI時(shí),主VI連同它所有子VI的代碼和數(shù)據(jù)段都會(huì)被調(diào)入內(nèi)存,但未打開的前面板和框圖并不會(huì)被調(diào)入內(nèi)存,只有當(dāng)主動(dòng)查看VI的前面板或框圖時(shí),才會(huì)被調(diào)用?;贚abVIEW的這種內(nèi)存管理特性,介紹幾個(gè)優(yōu)化LabVIEW程序的內(nèi)存管理方法。
2.2.1 子VI的使用
一個(gè)復(fù)雜的自動(dòng)控制系統(tǒng)的程序往往需要實(shí)現(xiàn)多個(gè)功能,將每個(gè)功能模塊用單獨(dú)子VI實(shí)現(xiàn),雖然會(huì)增加額外的前面板和框圖空間,但并不增加額外的代碼和數(shù)據(jù)空間,因此也不會(huì)占用額外的內(nèi)存資源。使用子VI還可以方便LabVIEW在結(jié)束子VI運(yùn)行時(shí)及時(shí)回收內(nèi)存資源,更進(jìn)一步改善了內(nèi)存的使用效率。
2.2.2 動(dòng)態(tài)調(diào)用子VI
自動(dòng)控制系統(tǒng)中有些功能在程序運(yùn)行過(guò)程中只需要執(zhí)行一次,例如:系統(tǒng)的自檢功能;有些功能在整個(gè)程序運(yùn)行中需要不斷調(diào)用,例如:設(shè)備控制部分和數(shù)據(jù)采集部分。不常用的自檢功能采用動(dòng)態(tài)調(diào)用VI方式,即只有在調(diào)用時(shí)該子VI時(shí)才加載到內(nèi)存中,運(yùn)行完后在內(nèi)存中清除此VI;對(duì)常用功能采用普通調(diào)用方式,即系統(tǒng)在運(yùn)行程序時(shí)就將此VI加載到內(nèi)存中,只有退出主程序時(shí),該VI才從內(nèi)存中清除。動(dòng)態(tài)調(diào)用程序框圖如圖2所示。
圖2 動(dòng)態(tài)調(diào)用VI程序圖
合理利用兩種調(diào)用方式,可以提高內(nèi)存利用率,避免不常用VI長(zhǎng)期占用內(nèi)存空間。
2.2.3 數(shù)據(jù)備份及緩存重用
自動(dòng)控制系統(tǒng)中的數(shù)據(jù)處理部分,往往要涉及到大量的數(shù)據(jù)運(yùn)算,有時(shí)要求把采集到的數(shù)據(jù)顯示成波形,LabVIEW程序主要是數(shù)據(jù)流驅(qū)動(dòng)型的。數(shù)據(jù)傳遞到不同節(jié)點(diǎn)時(shí)往往需要復(fù)制一個(gè)副本。當(dāng)對(duì)大的數(shù)組進(jìn)行運(yùn)算時(shí),內(nèi)存消耗很大,就是因?yàn)槌绦蛏闪诉^(guò)多的副本。
有些LabVIEW節(jié)點(diǎn)可以緩存重用,合理利用這些節(jié)點(diǎn)可以有效的提高內(nèi)存使用率,減少備份。
1)移位寄存器的使用
移位寄存器是內(nèi)存優(yōu)化的一個(gè)重要節(jié)點(diǎn),其在循環(huán)結(jié)構(gòu)的兩端是強(qiáng)制使用同一塊內(nèi)存的。圖3是對(duì)實(shí)現(xiàn)同一功能的兩種LabVIEW節(jié)點(diǎn)的編程比較。
圖3 移位寄存器節(jié)點(diǎn)比較
經(jīng)過(guò)內(nèi)存查看工具發(fā)現(xiàn)第一種方式大概占用了3.4 M的內(nèi)存空間,第二種方式僅占用了1.2 M的內(nèi)存空間。
2)元素同址操作
元素同址節(jié)點(diǎn)是另外一種強(qiáng)制數(shù)據(jù)緩存重用內(nèi)存的一種方式。該節(jié)點(diǎn)用于數(shù)組的索引、替換,簇的綁定和解除以及任意元素的緩存重用,可以使更新數(shù)據(jù)或簇中元素時(shí),不進(jìn)行數(shù)據(jù)備份。圖4是同址操作結(jié)構(gòu)的程序框圖。
圖4 元素同址節(jié)點(diǎn)應(yīng)用
2.2.4 全局變量和局部變量的應(yīng)用
在自動(dòng)控制系統(tǒng)的人機(jī)交互編程中往往會(huì)用到大量的界面操作,針對(duì)同一控件的讀寫操作往往出現(xiàn)在程序的不同位置。這時(shí)就會(huì)用到界面元素的屬性特點(diǎn)或者使用局部變量來(lái)實(shí)現(xiàn)操作。另外,在數(shù)據(jù)處理的編程部分中,有些復(fù)雜的算法往往需要順序結(jié)構(gòu)多步實(shí)現(xiàn),這時(shí)也會(huì)用到局部變量來(lái)進(jìn)行參數(shù)的傳遞。圖5是兩種編程方式的比較。
圖5 局部變量使用比較
經(jīng)過(guò)測(cè)試發(fā)現(xiàn),第一種方式的運(yùn)行時(shí)間是191 ms,占用內(nèi)存42.2 M;第二種方式的運(yùn)行時(shí)間是159 ms,占用內(nèi)存9.0 M。
局部變量和全局變量都會(huì)涉及到數(shù)據(jù)的備份,對(duì)某些大型數(shù)組的操作會(huì)導(dǎo)致內(nèi)存的大量占用,可以利用以下方式避免局部變量的應(yīng)用。
錯(cuò)誤簇的方式不僅能使數(shù)據(jù)的傳輸保持一定的順序,而且可以避免局部變量的使用。錯(cuò)誤簇的例子如圖6所示。
全局變量除了有內(nèi)存?zhèn)浞莸谋撞≈?,還存在競(jìng)爭(zhēng)的問(wèn)題。在程序的任何地方都可以隨意更改全局變量的值,容易造成其值被莫名其妙更改,且不便于程序的調(diào)試。全局變量在編程中可以通過(guò)使用隊(duì)列或者通告、事件結(jié)構(gòu)等方式來(lái)盡量避免。
圖6 錯(cuò)誤簇的妙用
2.2.5 防止內(nèi)存泄露
在控制系統(tǒng)的設(shè)備控制部分和數(shù)據(jù)采集部分以及文件I/O部分,會(huì)經(jīng)常用到設(shè)備端口的配置、采集卡任務(wù)的創(chuàng)建以及文件引用的創(chuàng)建。如果忘記關(guān)閉這些引用,就會(huì)導(dǎo)致內(nèi)存泄露,由于內(nèi)存泄漏是動(dòng)態(tài)產(chǎn)生的,我們無(wú)法通過(guò)VI屬性面板來(lái)查看,但可以通過(guò)Windows自帶的任務(wù)管理工具來(lái)查看。也可以使用LabVIEW的Profile(Tools>>Advanced>>Profile VIs)工具來(lái)查看某個(gè)VI運(yùn)行時(shí)內(nèi)存的分配情況。
圖7是控制儀器和文件打開和關(guān)閉引用的例子。
圖7 防止內(nèi)存泄露的程序框圖
2.2.6 減少數(shù)據(jù)備份
盡量使用占用資源較小的數(shù)據(jù)類型,例如使用16位整型數(shù)據(jù),而不是雙精度浮點(diǎn)數(shù);盡量要在循環(huán)內(nèi)進(jìn)行大量數(shù)據(jù)的運(yùn)算操作;合理利用內(nèi)聯(lián)VI。
以一套傳感器的壓力溫度性能檢測(cè)系統(tǒng)為例,對(duì)內(nèi)存管理進(jìn)行實(shí)例分析。本系統(tǒng)的基本組成如圖9所示。
該系統(tǒng)是用于檢測(cè)傳感器在不同溫度、不同壓力情況下的輸出性能。主要實(shí)現(xiàn)的功能在圖10中列出。
圖9 壓力溫度試驗(yàn)系統(tǒng)
圖10 軟件功能框圖
整個(gè)程序采用事件驅(qū)動(dòng)機(jī)制,將事件響應(yīng)節(jié)點(diǎn)放在順序框圖中,第一步是對(duì)硬件各種引用的打開操作,并進(jìn)行差錯(cuò)管理,一旦有錯(cuò)誤就關(guān)閉引用,以避免出現(xiàn)錯(cuò)誤時(shí)導(dǎo)致引用無(wú)法關(guān)閉而引起內(nèi)存泄露。所有與主要功能無(wú)關(guān)的界面操作均在此步中實(shí)現(xiàn),以避免在進(jìn)行主要功能時(shí)影響運(yùn)行效率;順序的第二部分是主要功能的實(shí)現(xiàn),此部分全局變量主要用于存儲(chǔ)數(shù)值常量包括一些硬件的命令字符串,在自動(dòng)控制循環(huán)中應(yīng)用移位寄存器來(lái)實(shí)現(xiàn)數(shù)據(jù)的傳輸,例如壓力控制部分,需要循環(huán)得到實(shí)際壓力值,并通過(guò)平均值判斷是否到達(dá)指定標(biāo)準(zhǔn)值,此時(shí)應(yīng)用移位寄存器而不是直接的數(shù)組累加方式來(lái)實(shí)現(xiàn)壓力值的平均值求取,溫度控制也類似;為了得到傳感器的性能分析,需要對(duì)采集到的大量數(shù)據(jù)進(jìn)行數(shù)學(xué)計(jì)算,這時(shí)盡量應(yīng)用錯(cuò)誤簇取代局部變量的應(yīng)用來(lái)實(shí)現(xiàn)計(jì)算的先后順序,且在數(shù)據(jù)運(yùn)算時(shí)盡量保持運(yùn)算中數(shù)值類型的一致性;順序的最后一步是對(duì)各種引用的正常關(guān)閉,以及文件的操作、界面元素的恢復(fù)等。
整個(gè)程序本著優(yōu)化內(nèi)存管理的思路,實(shí)現(xiàn)了要求的所有功能。
[1]李周華,嚴(yán)毅.軟件設(shè)計(jì)中的性能優(yōu)化與內(nèi)存管理[C]//廣西計(jì)算機(jī)學(xué)會(huì)——2004年學(xué)術(shù)年會(huì)論文集.2004.
[2]Jeffrey Richter.Windows核心編程 [M].北京:機(jī)械工業(yè)出版社,2000.
[3]魏海濤,姜昱明,李建武,等.內(nèi)存管理機(jī)制的高效實(shí)現(xiàn)研究[J].計(jì)算機(jī)工程與設(shè)計(jì),2009(16):3708-3712.