Perl多進(jìn)程技術(shù)在自動(dòng)化測(cè)試腳本中用法指導(dǎo)
Perl多進(jìn)程的用戶接口是 fork() 函數(shù)以及對(duì)系統(tǒng) fork 函數(shù)封裝的一些 module,本文向大家介紹一下應(yīng)用Perl多進(jìn)程技術(shù)到自動(dòng)化測(cè)試腳本,首先我們來(lái)看一下Perl多進(jìn)程的概念。
Perl多進(jìn)程
Perl 語(yǔ)言是一種非常強(qiáng)大的腳本語(yǔ)言,其廣泛應(yīng)用于系統(tǒng)維護(hù),CGI(Common Gateway Interface)編程,數(shù)據(jù)庫(kù)編程和自動(dòng)化測(cè)試中。
多任務(wù)和并發(fā)處理一度被看作是判定優(yōu)異操作系統(tǒng)的一個(gè)特性;同樣任何優(yōu)秀從而流行的編程語(yǔ)言都會(huì)有并發(fā)的應(yīng)用,而且都有各自的實(shí)現(xiàn)方法。Perl 最開(kāi)始在并發(fā)方面的應(yīng)用就是Perl多進(jìn)程。
Perl多進(jìn)程的用戶接口是 fork() 函數(shù)以及對(duì)系統(tǒng) fork 函數(shù)封裝的一些 module。我們?cè)谑褂?Perl 語(yǔ)言編程時(shí),如果一個(gè)任務(wù)的某一個(gè)段可以或者需要并發(fā)很多執(zhí)行,那么我們就會(huì)使用 Perl 的Perl多進(jìn)程編程,例如同時(shí)向數(shù)據(jù)庫(kù)遞交多個(gè)記錄的查詢,同時(shí)完成多個(gè)系統(tǒng)信息的收集等等。
Perl 的Perl多進(jìn)程是這樣實(shí)現(xiàn)的:主進(jìn)程每 fork 一個(gè)子進(jìn)程,會(huì)把當(dāng)前(主進(jìn)程的)內(nèi)存空間的所有變量都復(fù)制一份傳到新的進(jìn)程里面,達(dá)到數(shù)據(jù)共享的目的。此外,主進(jìn)程和子進(jìn)程可以通過(guò)信號(hào)、管道等來(lái)通信。
在處理并發(fā)的方案中,Perl多進(jìn)程依靠?jī)?nèi)存空間獨(dú)享提供了優(yōu)秀的容錯(cuò)性和健壯性。一個(gè)Perl多進(jìn)程的系統(tǒng)不會(huì)由于其中一個(gè)進(jìn)程的狀態(tài)不良而崩潰,每個(gè)進(jìn)程都相對(duì)獨(dú)立地運(yùn)作,很少會(huì)相互影響。
內(nèi)存空間獨(dú)享也造就了Perl多進(jìn)程不可避免的劣勢(shì):資源負(fù)荷以及通信復(fù)雜,對(duì)于 Perl 來(lái)說(shuō),每個(gè)子進(jìn)程都可以看作主進(jìn)程的拷貝,這多少有些內(nèi)存浪費(fèi),而且主進(jìn)程的關(guān)鍵變量如果是“淺復(fù)制”到子進(jìn)程的話,將會(huì)帶來(lái)一些意想不到的錯(cuò)誤。另外,進(jìn)程的創(chuàng)建和回收會(huì)帶來(lái)許多額外的負(fù)載,因此應(yīng)當(dāng)盡量避免頻繁地創(chuàng)建進(jìn)程。
Perl多進(jìn)程之間的通信方式有 socket,管道,信號(hào)量等。在 Linux 平臺(tái)上,對(duì)于進(jìn)程間大量信息的交互情況,最常用的是文件;這在用戶空間進(jìn)程和系統(tǒng)內(nèi)核空間進(jìn)程之間的通信中的最為常用。在談起 Perl Perl多進(jìn)程的時(shí)候,不可避免的要說(shuō)說(shuō)它與 Perl 多線程的關(guān)系。
應(yīng)用Perl多進(jìn)程技術(shù)到自動(dòng)化測(cè)試腳本
在自動(dòng)化測(cè)試中,利用RationalBuildForge作為測(cè)試管理和監(jiān)控工具,90%以上的測(cè)試腳本都采用Perl腳本。采用了模塊化編程,并大量使用CPAN提供的module。由于很多module都不是線程安全的,同時(shí)為了提高腳本開(kāi)發(fā)效率,也會(huì)在一個(gè)腳本中直接調(diào)用另外一個(gè)腳本,所以選擇在自動(dòng)化測(cè)試框架中應(yīng)用Perl多進(jìn)程。
自動(dòng)化測(cè)試腳本使用Perl多進(jìn)程大致分為兩種情況。一種是Testconsole需要同時(shí)操作十幾個(gè)設(shè)備,例如用于主機(jī)和存儲(chǔ)互連的光纖交換機(jī),用于光纖物理層斷開(kāi)測(cè)試的交換機(jī)APCON等。這類(lèi)測(cè)試的特點(diǎn)是需要同時(shí)操作10幾個(gè)或者20幾個(gè)的測(cè)試對(duì)象,對(duì)它們的操作是配置操作,而且配置腳本都會(huì)成功,主進(jìn)程只需要所有子進(jìn)程執(zhí)行完畢就認(rèn)為所有子任務(wù)已經(jīng)完成,然后可以進(jìn)行后續(xù)的操作。因此采用一種較為簡(jiǎn)單的Perl多進(jìn)程編程方式。下面是針對(duì)這種情況的Perl多進(jìn)程處理的代碼示例。
清單1.Perl多進(jìn)程處理的代碼
- our@cmd=("./apcon_2052.exp119.11.217.27A15B15",
- "./apcon_2058.exp119.11.217.65adminteamw0rkA05A06",
- "./apcon_2052.exp119.11.217.27B09D09");
- our$zombies=0;
- our$kid_proc_num=0;
- $SIG{CHLD}=sub{$zombies++};
- for(my$i=0;$i<@cmd;$i++){
- my$pid=fork();
- if(!defined($pid)){exit1;}
- unless($pid){
- system"$cmd[$i]";
- exit0;
- }
- $kid_proc_num++;
- }
- while(1){
- if($zombies>0){
- $zombies=0;
- my$collect;
- while(($collect=waitpid(-1,WNOHANG))>0){
- $kid_proc_num--;
- }
- }
- if($kid_proc_num==0){last;}
- else{next;}
- }
以上的代碼采用Perl多進(jìn)程方式同時(shí)處理了對(duì)3個(gè)測(cè)試設(shè)備的配置操作,然后主進(jìn)程等待所有配置操作完成,再進(jìn)行后續(xù)的測(cè)試。
另外一種情況較為復(fù)雜,就是經(jīng)常需要針對(duì)數(shù)百個(gè)主機(jī)和存儲(chǔ)進(jìn)行配置、狀態(tài)查詢等,而且配置結(jié)果和查詢狀態(tài)需要返回主進(jìn)程處理,然后根據(jù)結(jié)果數(shù)據(jù)再?zèng)Q定如何繼續(xù)。對(duì)于這種情況,主進(jìn)程需要生成數(shù)百個(gè)子進(jìn)程,而且每個(gè)子進(jìn)程都有大量的信息返回給主進(jìn)程來(lái)處理。這樣處理數(shù)百個(gè)子進(jìn)程的生成:由于Perl多進(jìn)程方式占用系統(tǒng)資源較多,因此設(shè)定一個(gè)允許主進(jìn)程同時(shí)運(yùn)行的最多子進(jìn)程數(shù)目,然后在有子進(jìn)程結(jié)束時(shí),主進(jìn)程再生成新的子進(jìn)程至所有的子任務(wù)完成。這樣處理主進(jìn)程和子進(jìn)程的通信和信息交互:由于測(cè)試Perl腳本運(yùn)行平臺(tái)為L(zhǎng)inux,它是帶有BSD風(fēng)格的POSIX兼容的系統(tǒng),會(huì)提供可靠的信號(hào),所以仍然使用系統(tǒng)提供信號(hào)的來(lái)獲取子進(jìn)程結(jié)束的消息;對(duì)于子進(jìn)程的返回信息,采用為每個(gè)子進(jìn)程產(chǎn)生一個(gè)臨時(shí)文件用于存儲(chǔ)返回的所有信息,最后主進(jìn)程來(lái)處理這些文件從而獲取每個(gè)子任務(wù)的結(jié)果信息。如下是為這種情況設(shè)計(jì)的Perl多進(jìn)程處理方式的軟件流圖。
圖3.軟件流圖
下面以登錄每個(gè)主機(jī)檢查運(yùn)行狀態(tài)的例子給出Perl多進(jìn)程處理數(shù)百個(gè)子任務(wù)的代碼。
清單2.Perl多進(jìn)程處理數(shù)百個(gè)子任務(wù)
- usestrict;
- usewarnings;
- usePOSIX":sys_wait_h";
- our@IP=&getAllHostIP();
- our$TOTAL_TASK=@IP;#assumewehave300hosts
- our$MAX_LIVE_PROC=24;#MaximumnumberofsubProcessallowedtoco-exist
- our@result_filename=();
- our$zombies=0;
- $SIG{CHLD}=sub{$zombies++};#handlemessagefromkernel
- our$handled_task=1;
- our$cur_live_proc=1;
- my$pid=fork();
- unless($pid){
- my$filename=&getUniqueFilename();
- push@result_filename,$filename;
- system"./checkHost$IP[$handled_task-1]$uid$psw$filename";
- exit0;
- }
- while($cur_live_proc>0){
- if($zombies>0){
- $zombies=0;
- my$collect=0;
- while(($collect=waitpid(-1,WNOHANG))>0){
- $cur_live_proc--;
- }
- }
- if(($cur_live_proc<$MAX_LIVE_PROC)and($handled_task<$TOTAL_TASK)){
- $handled_task++;
- $cur_live_proc++;
- my$pid=fork();
- unless($pid){
- my$filename=&getUniqueFilename();
- push@result_filename,$filename;
- system"./checkHost$IP[$handled_task-1]$uid$psw$filename";
- exit0;
- }
- }else{
- next;
- }
- }
- &checkResults();
小結(jié)
根據(jù)常見(jiàn)的設(shè)備系統(tǒng)測(cè)試自動(dòng)化平臺(tái)的特點(diǎn)和要求,把Perl的Perl多進(jìn)程技術(shù)應(yīng)用到了測(cè)試腳本中,極大地提高了測(cè)試效率。
Perl多進(jìn)程已經(jīng)很長(zhǎng)的發(fā)展歷史,而且應(yīng)用廣泛,技術(shù)成熟。Perl多進(jìn)程在健壯性和容錯(cuò)性方面表現(xiàn)更好,每個(gè)進(jìn)程都擁有獨(dú)立的內(nèi)存空間,并行的幾個(gè)進(jìn)程一般來(lái)說(shuō)不會(huì)相互干擾;當(dāng)然,相應(yīng)的,Perl多進(jìn)程的系統(tǒng)開(kāi)銷(xiāo)也比較大,而且進(jìn)程間通信也變得復(fù)雜一些。妥善地處理Perl多進(jìn)程生成和進(jìn)程間的通信,會(huì)很好地改善自動(dòng)化測(cè)試的運(yùn)行效率以及穩(wěn)定性。
【編輯推薦】