用fork函數創建子進程後,子進程往往要調用一種exec函數以執行另一個程序。當進程調用一種exec函數時,該進程完全由新程序代換,而新程序則從其
main函數開始執行。因爲調用exec並不創建新進程,所以前後的進程ID並未改變。exec只是用另一個新程序替換了當前進程的正文、數據、堆和棧段。有六種不同的exec函數可供使用,它們常常被統稱爲exec函數。這些exec函數都是UNIX進程控制函數。用fork可以創建新進程,用exec可以執行新的程序。exit函數和兩個wait函數處理終止和等待終止。這些是我們需要的基本的進程控制函數。
exec函數族的作用是根據指定的文件名找到可執行文件,並用它來取代調用進程的內容,換句話說,就是在調用進程內部執行一個可執行文件。這裏的可執行文件既可以是二進制文件,也可以是任何Linux下可執行的腳本文件,如果不是可以執行的文件,那麼就解釋成爲一個shell文件
與一般情況不同,exec函數族的函數執行成功後不會返回,因爲調用進程的實體,包括代碼段,數據段和堆棧等都已經被新的內容取代,只留下進程ID等一些表面上的信息仍保持原樣,頗有些神似"三十六計"中的"金蟬脫殼"。看上去還是舊的軀殼,卻已經注入了新的靈魂。只有調用失敗了,它們纔會返回一個-1,從原程序的調用點接着往下執行。
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 execvpe(const char *file, char *const argv[],char *const envp[]);
首先execl和execv開頭的函數的區別是:execl開頭的函數採用了我們更容易習慣的方式,把參數一個一個列出來,然後以一個NULL表示結束。execv開頭的函數是以"char *argv[]"這樣的形式傳遞命令行參數。
注:
- 命令行參數的第一個參數一般爲程序名本身。最後一個參數爲NULL;
- 當exec函數執行完畢後,便立即退出當前進程,不執行後面的語句,所以常常先fork一個子進程,然後調用exec函數。
- 其中只有execve是真正意義上的系統調用,其它都是在此基礎上經過包裝的庫函數。
不加:搜索路徑名,要求參數path必須是一個完整的路徑名
p:只賦一個文件名即可,函數會到環境變量PATH目錄中尋找可執行文件。否則要求參數path必須是一個完整的路徑名
e:函數傳遞指定參數envp,允許改變子進程的環境,無後綴e時,子進程使用當前程序的環境。envp也是一個以NULL結尾的字符串數組指針
返回值:出錯返回-1,成功不返回值。
system()會調用fork()產生子進程,由子進程來調用/bin/sh-c string來執行參數string字符串所代表的命令,此命令執行完後隨即返回原調用的進程。在調用system()期間SIGCHLD 信號會被暫時擱置,SIGINT和SIGQUIT 信號則會被忽略。
int system(const char * string);
如果exec()失敗,表示不能執行Shell,返回值相當於Shell執行了exit(127)功能:執行shell命令參數:string:要執行的shell命令返回值:如果fork()失敗 返回-1:出現錯誤
如果執行成功則返回子Shell的終止狀態如果system()在調用/bin/sh時失敗則返回127,其他失敗原因返回-1。若參數string爲空指針(NULL),則返回非零值>;。如果system()調用成功則最後會返回執行shell命令後的返回值,但是此返回值也有可能爲 system()調用/bin/sh失敗所返回的127,因此最好能再檢查errno 來確認執行成功。