進程控制開發之:Linux進程控制編程
(4)函數使用注意點。
fork()函數使用一次就創建一個進程,所以若把fork()函數放在了ifelse判斷語句中則要小心,不能多次使用fork()函數。
小知識 | 由于fork()完整地復制了父進程的整個地址空間,因此執行速度是比較慢的。為了加快fork()的執行速度,有些UNIX系統設計者創建了vfork()。vfork()也能創建新進程,但它不產生父進程的副本。它是通過允許父子進程可訪問相同物理內存從而偽裝了對進程地址空間的真實拷貝,當子進程需要改變內存中數據時才復制父進程。這就是著名的“寫操作時復制”(copy-on-write)技術。 現在很多嵌入式Linux系統的fork()函數調用都采用vfork()函數的實現方式,實際上uClinux所有的多進程管理都通過vfork()來實現。 |
2.exec函數族
(1)exec函數族說明。
fork()函數是用于創建一個子進程,該子進程幾乎復制了父進程的全部內容,但是,這個新創建的進程如何執行呢?這個exec函數族就提供了一個在進程中啟動另一個程序執行的方法。它可以根據指定的文件名或目錄名找到可執行文件,并用它來取代原調用進程的數據段、代碼段和堆棧段,在執行完之后,原調用進程的內容除了進程號外,其他全部被新的進程替換了。另外,這里的可執行文件既可以是二進制文件,也可以是Linux下任何可執行的腳本文件。
在Linux中使用exec函數族主要有兩種情況。
n 當進程認為自己不能再為系統和用戶做出任何貢獻時,就可以調用exec函數族中的任意一個函數讓自己重生。
n 如果一個進程想執行另一個程序,那么它就可以調用fork()函數新建一個進程,然后調用exec函數族中的任意一個函數,這樣看起來就像通過執行應用程序而產生了一個新進程(這種情況非常普遍)。
(2)exec函數族語法。
實際上,在Linux中并沒有exec()函數,而是有6個以exec開頭的函數,它們之間語法有細微差別,本書在下面會詳細講解。
下表7.3列舉了exec函數族的6個成員函數的語法。
表7.3 exec函數族成員函數語法
所需頭文件 | #includeunistd.h> |
函數原型 | intexecl(constchar*path,constchar*arg,...) |
intexecv(constchar*path,char*constargv[]) | |
intexecle(constchar*path,constchar*arg,...,char*constenvp[]) | |
intexecve(constchar*path,char*constargv[],char*constenvp[]) | |
intexeclp(constchar*file,constchar*arg,...) | |
intexecvp(constchar*file,char*constargv[]) | |
函數返回值 | -1:出錯 |
這6個函數在函數名和使用語法的規則上都有細微的區別,下面就可執行文件查找方式、參數表傳遞方式及環境變量這幾個方面進行比較。
n 查找方式。
讀者可以注意到,表7.3中的前4個函數的查找方式都是完整的文件目錄路徑,而最后2個函數(也就是以p結尾的兩個函數)可以只給出文件名,系統就會自動按照環境變量“$PATH”所指定的路徑進行查找。
n 參數傳遞方式。
exec函數族的參數傳遞有兩種方式:一種是逐個列舉的方式,而另一種則是將所有參數整體構造指針數組傳遞。
在這里是以函數名的第5位字母來區分的,字母為“l”(list)的表示逐個列舉參數的方式,其語法為char*arg;字母為“v”(vertor)的表示將所有參數整體構造指針數組傳遞,其語法為*constargv[]。讀者可以觀察execl()、execle()、execlp()的語法與execv()、execve()、execvp()的區別。它們具體的用法在后面的實例講解中會具體說明。
這里的參數實際上就是用戶在使用這個可執行文件時所需的全部命令選項字符串(包括該可執行程序命令本身)。要注意的是,這些參數必須以NULL表示結束,如果使用逐個列舉方式,那么要把它強制轉化成一個字符指針,否則exec將會把它解釋為一個整型參數,如果一個整型數的長度char*的長度不同,那么exec函數就會報錯。
n 環境變量。
exec函數族可以默認系統的環境變量,也可以傳入指定的環境變量。這里以“e”(environment)結尾的兩個函數execle()和execve()就可以在envp[]中指定當前進程所使用的環境變量。
表7.4是對這4個函數中函數名和對應語法的小結,主要指出了函數名中每一位所表明的含義,希望讀者結合此表加以記憶。
表7.4 exec函數名對應含義
前4位 | 統一為:exec | |
第5位 | l:參數傳遞為逐個列舉方式 | execl、execle、execlp |
v:參數傳遞為構造指針數組方式 | execv、execve、execvp | |
第6位 | e:可傳遞新進程環境變量 | execle、execve |
p:可執行文件查找方式為文件名 | execlp、execvp |
(3)exec使用實例。
下面的第一個示例說明了如何使用文件名的方式來查找可執行文件,同時使用參數列表的方式。這里用的函數是execlp()。
/*execlp.c*/
#includeunistd.h>
#includestdio.h>
#includestdlib.h>
intmain()
{
if(fork()==0)
{
/*調用execlp()函數,這里相當于調用了ps-ef命令*/
if((ret=execlp(ps,ps,-ef,NULL))0)
{
printf(Execlperrorn);
}
}
}
在該程序中,首先使用fork()函數創建一個子進程,然后在子進程里使用execlp()函數。讀者可以看到,這里的參數列表列出了在shell中使用的命令名和選項。并且當使用文件名進行查找時,系統會在默認的環境變量PATH中尋找該可執行文件。讀者可將編譯后的結果下載到目標板上,運行結果如下所示:
$./execlp
PIDTTYUidSizeStateCommand
1root1832Sinit
2root0S[keventd]
3root0S[ksoftirqd_CPU0]
4root0S[kswapd]
5root0S[bdflush]
6root0S[kupdated]
7root0S[mtdblockd]
8root0S[khubd]
35root2104S/bin/bash/usr/etc/rc.local
36root2324S/bin/bash
41root1364S/sbin/inetd
53root14260S/Qtopia/qtopia-free-1.7.0/bin/qpe-qws
54root11672Squicklauncher
65root0S[usb-storage-0]
66root0S[scsi_eh_0]
83root2020Rps-ef
$env
……
PATH=/Qtopia/qtopia-free-1.7.0/bin:/usr/bin:/bin:/usr/sbin:/sbin
……
linux操作系統文章專題:linux操作系統詳解(linux不再難懂)
評論