第十四章 進程管理
一、 Perl
中,能夠利用system 函數啓動子進程,子程序執行相應的命令並繼承Perl的標準輸入、標準輸出以及標準錯誤;一般提供給system 函數的參數就是通常在shell所鍵入的命令,當參數裏有相似於「$HOME」的環境變量時,應該將參數放在單引號中(雙引號中$開頭的字符串會被看成變量進行替換)或者入在雙引號中並將符號「$」進行轉義;
二、
當子進程運行時,Perl會一直等待直到子進程結束,固然也能夠將子進程放在後臺進行,這種狀況下Perl將無以得知子進程的存在及運行情況;當命令「很簡單」時,Perl不會用到shell,而是直接啓動命令,並會在必要時使用繼承而來的PATH變量;
三、
使用system 函數時,若是爲其指定了多個參數(多個參數間要互相隔離),則函數的整個執行過程不會用到shell,如:
system 「/bin/sh」, 「-c」, $command_line;
在Unix中,函數執行返回0表示一切正常,非0表示不執行不成功,這恰與Perl的函數相反;
四、
不一樣於system 函數會讓Perl暫停並建立一個子進程來執行所要求的命令,exec 函數會讓Perl進程本身去執行所要求的命令,此時,Perl會找到並啓動指定的程序然後「跳進該程序」,而原有的Perl進程將再也不存在,程序執行結束後於是也沒有Perl進程能夠返回,因而會直接返回至提示符下;exec 函數不多單獨使用,更多的是和fork一塊兒使用;
五、
在啓動其它進程時,有時候須要設定其運行環境;Perl中,環境變量可經過特殊散列%ENV取得,其中每一個散列鍵都表明一個環境變量;在程序開始運行時,%ENV會保留從父進程(一般是shell)繼承而來的設定值,於是,能夠經過改變散列來改變所要用到的環境變量;
六、
使用system 和 exec 時,也能夠對其執行結果進行捕獲並保存至變量(能夠是標量,也能夠是列表)中,方法是使用反引號「`」來代替雙引號或單引號,反引號裏要執行的命令至關於system 的單參數形式,而且會以被雙引號揪住的字符串的形式進行解釋,裏面的反斜線轉義序列與變量都會被適當地展開;如:
$mydate = `date`;
七、
反引號要等效於單引號會很麻煩,也沒有簡單的辦法使之對應到system 的多參數版本,並且若是反引號內的命令很複雜的話,shell(一般是/bin/sh)就會被自動啓動並用來解釋該命令;使用單引號時即使不用變量捕獲其輸出,Perl依然會浪費力氣地獲取其輸出結果;此外,反引號內的程序會繼承Perl的標準輸入和輸出,所以,其錯誤信息輸出會被送往當前標準輸出,也會在須要時從當前標準輸入等待輸入信息,而這些命令不是由當前用戶本身啓動,所以用戶可能會在看到這些信息時疑惑不解;所以,慎用反引號;
八、
若是反引號中程序的輸出有許多行,那麼在標量上下文會返回成一個長字符串,而在列表上下文會返回由各行輸出組成的列表;
九、
如前面的執行方式,處理同步進程的方法都是由Perl 掌控全局:啓動一個命令,而後等着它結束,或許還會獲取其輸出;不過,Perl也能夠啓動子進程,直到結束以前,它們都會持續和Perl交換信息;要啓動併發子進程,須要將命令放在open 調用的文件名部分,而且在它前面或者後面加上豎線符號「|」,這種方法即將進程視爲文件句柄,也稱爲管道式打開;如:
open DATE, 「date|」 or die 「Cannot pipe from date: $!」;
open MAIL, 「|mail merlyn」 or die 「Cannot pipe to mail: $!」;
豎線符號在右邊表示該命令執行時它的標準輸出會鏈接到供程序讀取的相應句柄,因而第一個例子就像在shell中輸入 date | your_program 同樣;豎線符號在左邊表示該命令的標準輸入會鏈接到供程序寫入的相應文件句柄,如第二例形如your_mail | mail Merlyn 命令;
十、
如此,想要從「以讀取模式打開的文件句柄」中取得數據,只要採用正常的文件讀取方式就能夠了,如:my $now = <DATE>; 想傳遞數據給「以等待讀入數據模式打開的文件句柄」進程,只要利用輸出至文件句柄的print運算便可,如:print MAIL 「The time is now $now」; ;
Perl
能夠對
Unix
以及其它系統上「管理進程用的低級系統調用」進行近乎直接的控制,如使用
fork
函數來建立進程;當調用
fork
函數時,若是是調用系統的
fork
函數來建立一個新的進程,就是經過複製解釋器來模仿它;調用
fork
函數時,若是調用成功,就會建立一個等同於父進程的子進程,該子進程繼承了父進程的全部屬性,好比環境變量;兩個進程間的惟一差異在於
fork
調用的返回值,在子進程中,返回
0
,在父進程中,返回子進程的
PID
;若是
fork
不成功,會返回
undef
;