博客原地址:http://blog.chinaunix.net/uid-21411227-id-1826717.html
1.exec家族一共有六個函數,分別是:(1)int execl(const char *path, const char *arg, ......);
(2)int execle(const char *path, const char *arg, ...... , char * const envp[]);
(3)int execv(const char *path, char *const argv[]);
(4)int execve(const char *filename, char *const argv[], char *const envp[]);
(5)int execvp(const char *file, char * const argv[]);
(6)int execlp(const char *file, const char *arg, ......);
其中只有execve是真正意義上的系統調用,其它都是在此基礎上經過包裝的庫函數。exec函數族的作用是根據指定的文件名找到可執行文件,並用它來取代調用進程的內容,換句話說,就是在調用進程內部執行一個可執行文件。這裡的可執行文件既可以是二進制文件,也可以是任何Linux下可執行的腳本文件。
與一般情況不同,exec函數族的函數執行成功後不會返回,因為調用進程的實體,包括代碼段,數據段和堆棧等都已經被新的內容取代,只留下進程ID等一些表面上的信息仍保持原樣,頗有些神似"三十六計"中的"金蟬脫殼"。看上去還是舊的軀殼,卻已經注入了新的靈魂。只有調用失敗了,它們才會返回一個-1,從原程序的調用點接著往下執行。
2.它們之間的區別:第一個區別是:
前四個取路徑名做為參數,後兩個取文件名做為參數,如果文件名中不包含 “/” 則從PATH環境變量中搜尋可執行文件, 如果找到了一個可執行文件,但是該文件不是連接編輯程序產生的可執行代碼文件,則當做shell腳本處理。
第二個區別:前兩個和最後一個函數中都包括“ l ”這個字母 ,而另三個都包括“ v ”, "
l "代表 list即表 ,而" v "代表 vector即矢量,也是是前三個函數的參數都是以list的形式給出的,但最後要加一個空指針,如果用常數0來表示空指針,則必須將它強行轉換成字符指針,否則有可能出錯。,而後三個都是以矢量的形式給出,即數組。
最後一個區別:與向新程序傳遞環境變量有關,如第二個和第四個以e結尾的函數,可以向函數傳遞一個指向環境字符串指針數組的指針。即自個定義各個環境變量,而其它四個則使用進程中的環境變量。
3.實例講解:(1)在平時的編程中,如果用到了exec函數族,一定記得要加錯誤判斷語句。先判斷execl的返回值,如果出錯,可以用perror(
)函數打印出錯誤信息。
如:if (execl(“path”,”..””(char
*)0) < 0)
{
perror(“execl error!”);
}
如果調用出錯,可輸出:execl error!: 錯誤原因 這樣可方便查找出錯原因
(2)注意下面書寫格式:
先定義一個指針數組:char *argv[]={“ls”,”-l”,(char
*)0}
用execv調用ls: execv(“/bin/ls”,argv)
如果用execvp
execvp(“ls”,argv) //直接寫ls就可以了
注意:execl調用shell 時,要在shell腳本中指明使用的shell版本:#!/bin/bash。在命令行下執行shell腳本,系統為它自動打開一個shell,在程序中沒有shell,在調用shell腳本時,會出錯,所以要在shell腳本中先打開shell。