exec函數族
一簇函數
exec函數族,顧名思義,就是一簇函數,他把當前進程映像替換成新的程序文件,而且該程序通常main函數開始執行。
使用exec函數族主要有兩種情況:
(1)當進程認為自己不能再為系統和用戶做出任何貢獻時,就可以調用exec函數族中的任意一個函數讓自己重生。
(2)如果一個進程想執行另一個程序,那麼它就可以調用fork函數新建一個進程,然後調用exec函數族中的任意一個函數,這樣看起來就像通過執行應用程序而產生了一個新進程(這種情況非常普遍)。
exec函數族共有6種不同形式的函數。這6個函數可以劃分為兩組:
(1)execl、execle和execlp。
(2)execv、execve和execvp。
這兩組函數的不同在於exec后的第一個字元,第一組是l,在此稱,為execl系列;第二組是v,在此稱為execv系列。這裡的l是list(列表)的意思,表示execl系列函數需要將每個命令行參數作為函數的參數進行傳遞;而v是vector(矢量)的意思,表示execv系列函數將所有函數包裝到一個矢量數組中傳遞即可。
參數說明:
path:要執行的程序路徑。可以是絕對路徑或者是相對路徑。在execv、execve、execl和execle這4個函數中,使用帶路徑名的文件名作為參數。
file:要執行的程序名稱。如果該參數中包含“/”字元,則視為路徑名直接執行;否則視為單獨的文件名,系統將根據PATH環境變數指定的路徑順序搜索指定的文件。
argv:命令行參數的矢量數組。
envp:帶有該參數的exec函數可以在調用時指定一個環境變數數組。其他不帶該參數的exec函數則使用調用進程的環境變數。
arg:程序的第0個參數,即程序名自身。相當於argv[O]。
…:命令行參數列表。調用相應程序時有多少命令行參數,就需要有多少個輸入參數項。注意:在使用此類函數時,在所有命令行參數的最後應該增加一個空的參數項(NULL),表明命令行參數結束。
返回值:一1表明調用exec失敗,無返回表明調用成功。
用fork函數創建子進程后,子進程往往要調用一種exec函數以執行另一個程序。當進程調用一種exec函數時,該進程完全由新程序代換,而新程序則從其 main函數開始執行。因為調用exec並不創建新進程,所以前後的進程ID並未改變。exec只是用另一個新程序替換了當前進程的正文、數據、堆和棧段。有六種不同的exec函數可供使用,它們常常被統稱為exec函數。這些exec函數都是UNIX進程式控制制原語。用fork可以創建新進程,用exec可以執行新的程序。exit函數和兩個wait函數處理終止和等待終止。這些是我們需要的基本的進程式控制制原語。
說是exec系統調用,實際上在Linux中,並不存在一個exec()的函數形式,exec指的是一組函數,一共有6個,分別是:
#include
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
其中只有execve是真正意義上的系統調用,其它都是在此基礎上經過包裝的庫函數。
exec函數族的作用是根據指定的文件名找到可執行文件,並用它來取代調用進程的內容,換句話說,就是在調用進程內部執行一個可執行文件。這裡的可執行文件既可以是二進位文件,也可以是任何Linux下可執行的腳本文件,如果不是可以執行的文件,那麼就解釋成為一個shell文件,sh **執行!
上面6條函數看起來似乎很複雜,但實際上無論是作用還是用法都非常相似,只有很微小的差別。
參數argc指出了運行該程序時命令行參數的個數,數組argv存放了所有的命令行參數,數組envp存放了所有的環境變數。環境變數指的是一組值,從用戶登錄后就一直存在,很多應用程序需要依靠它來確定系統的一些細節,我們最常見的環境變數是PATH,它指出了應到哪裡去搜索應用程序,如 /bin;HOME也是比較常見的環境變數,它指出了我們在系統中的個人目錄。環境變數一般以字元串"XXX=xxx"的形式存在,XXX表示變數名,xxx表示變數的值。
值得一提的是,argv數組和envp數組存放的都是指向字元串的指針,這兩個數組都以一個NULL元素表示數組的結尾。
來看一下exec函數族,先把注意力集中在execve上:
int execve(const char *path, char *const argv[], char *const envp[]);
execve第1個參數path是被執行應用程序的完整路徑,第2個參數argv就是傳給被執行應用程序的命令行參數,第3個參數envp是傳給被執行應用程序的環境變數。
在這裡有點要注意,不管是arg0,還是argv[0]都必須是程序的可執行文件的名字,比如:
execl("/bin/echo", "echo", "executed by execl", NULL)中的echo;
execl("/bin/ls", "ls", "/azuo", "-la", (char *)0 )中的ls;
execlp("echo", "echo", "executed by execlp", NULL)中的echo;
留心看一下這6個函數還可以發現,前3個函數都是以execl開頭的,后3個都是以execv開頭的,它們的區別在於,execv開頭的函數是以"char *argv[]"這樣的形式傳遞命令行參數,而execl開頭的函數採用了我們更容易習慣的方式,把參數一個一個列出來,然後以一個NULL表示結束。這裡的NULL的作用和argv數組裡的NULL作用是一樣的。
這裡建議使用 (char *)0 代替NULL。
在全部6個函數中,只有execle和execve使用了char *envp[]傳遞環境變數,其它的4個函數都沒有這個參數,這並不意味著它們不傳遞環境變數,這4個函數將把默認的環境變數不做任何修改地傳給被執行的應用程序。而execle和execve會用指定的環境變數去替代默認的那些。
還有2個以p結尾的函數execlp和execvp,咋看起來,它們和execl與execv的差別很小,事實也確是如此,除execlp和 execvp之外的4個函數都要求,它們的第1個參數path必須是一個完整的路徑,如"/bin/ls";而execlp和execvp的第1個參數 file可以簡單到僅僅是一個文件名,如 "ls",這兩個函數可以自動到環境變數PATH制定的目錄里去尋找。
EXEC[一簇函數]
EXEC 是 EXECUTE 的縮寫.
exec命令有兩個用法:執行一個存儲過程,或者執行一個動態批次。