exec族的任一函數都不創建一個新的進程,而是在調用進程里面去執行新的程序。所以進程id不變,還是調用exec函數前的進程id,但是用戶空間的代碼和數據都更新了,變為新程序的代碼和數據了。
extern char **environ; //全局環境變量,導入到本文件即可直接使用
1. int execl(const char *path, const char *arg, ...);
功能:通過路徑+文件名來加載一個進程;path文件路徑;arg文件名稱;...可變參數,至少一個NULL
附:l即list
返回值:成功的情況下是沒有返回的,失敗時返回-1 。
舉例說明:
execl("/bin/ls", "ls", "-a", "-l", NULL); //path絕對路徑,如/bin/ls;文件名稱ls;后面三個可變參數,最后必須以NULL結束
2. int execlp(const char *file, const char *arg, ...);
功能:借助PATH環境變量加載一個進程,file要加載的程序的名稱
附:l即list;p即path
該函數需要配合PATH環境變量來使用,當PATH中所有目錄搜索后沒有參數file,則出錯返回。
該函數通常用來調用系統程序。如:ls、cp、cat等命令。
返回值:成功的情況下是沒有返回的,失敗時返回-1 。
舉例說明:
execlp("ls", "ls", "-a", "-l", NULL); //第一個ls是指查看PATH環境變量里的ls;第二個ls是名稱文件;后面是可變參數,NULL結束
3. int execle(const char *path, const char *arg, ..., char * const envp[]);
功能:加載指定路徑的程序,並為新程序復制最后一個環境變量
附:l即list;e即environment
舉例說明:
char* envp[] = {NULL};
execlp("ls", "ls", "-a", "-l", NULL, envp);
4. int execv(const char *path, char *const argv[]);
功能:加載指定路徑的程序
附:v即vector,命令行參數列表
舉例說明:
char* argv[] = {"ls", "-a", "-l", NULL};
execl("/bin/ls",argv);
5. int execvp(const char *file, char *const argv[]);
功能:加載path環境變量里的名稱為file的程序
附:v即命令行參數列表,p即path
int main(int argc, char *argv[]) {
pid_t pid = fork();
if (pid == 0) { //子進程里加載ls程序
char* argvv[] = {"ls", "-a", "-l", NULL};
execvp("ls", argvv);
perror("execlp"); exit(1); //只有execl函數執行失敗的情況下才有機會執行這兩句代碼,執行的成功話就有去無回了。
} else if (pid > 0) {
sleep(1); printf("parent\n");
}
return 0;
}
6. int execve(const char *filename, char *const argv[], char *const envp[]);
功能:加載指定的程序;filename必須是一個可執行程序或者一個以#! interpreter [optional-arg] 開始的腳本。
上面的五個exec函數是庫函數,這個是系統函數;上面的五個exec函數最終都是調用這個函數實現的。
總結:exec族函數的規律
exec函數一旦調用成功就有去無回了,去執行新的程序去了。只有失敗時才有返回,返回值為-1。所以我們直接在exec函數調用后直接調用perror()和exit(),不需要if判斷,因為失敗的情況才會執行。
函數名的意義的理解:
l (list) 命令行參數列表
p (path) 環境變量,環境變量搜素文件名稱file
v (vector) 命令行參數數組
e (environment) 環境變量數組,給新加載程序設置指定的環境變量
函數的相似性:
execlp——>execvp
|
execl ——>execv
|
execle——>execve
從左往右,可變參數轉為以NULL結尾的指針數組;從左往右, 從上往下,最后歸根結底都是調用execve函數實現的。