1. 基本概念
1.1 進程替換 vs. 進程創建
- 進程創建:使用
fork()
或clone()
等系統調用創建一個新的子進程,子進程是父進程的副本,擁有相同的代碼和數據。 - 進程替換:使用
exec
系列函數在當前進程中加載并執行一個新的程序,替換掉當前進程的映像,但保留PID、文件描述符等資源。
1.2?exec
系列函數
exec
系列函數用于在當前進程中執行一個新程序。常見的exec
函數包括:
這些函數的命名規則如下:
- 前綴:
exec
- 中間部分:
l
(list):參數以列表形式傳遞。v
(vector):參數以數組形式傳遞。
- 后綴:
e
:允許傳遞環境變量。p
:使用PATH
環境變量來查找可執行文件。
2. 常用的exec
函數
2.1?execl()
函數原型:
?
#include <unistd.h>int execl(const char *path, const char *arg, ... /* (char *) NULL */);
參數:
path
:要執行的可執行文件的路徑。arg
:第一個參數,通常是程序名。...
:可變參數列表,以NULL
結尾。
?例子:
#include <stdio.h>
#include <unistd.h>int main() {printf("Before execl\n");execl("/bin/ls", "ls", "-l", NULL);// 如果execl成功,以下代碼不會執行perror("execl failed");return 1;
}
2.2?execv()
函數原型:
#include <unistd.h>int execv(const char *path, char *const argv[]);
參數:
path
:要執行的可執行文件的路徑。argv
:參數數組,以NULL
結尾。
例子:
#include <stdio.h>
#include <unistd.h>int main() {char *args[] = { "ls", "-l", NULL };printf("Before execv\n");execv("/bin/ls", args);// 如果execv成功,以下代碼不會執行perror("execv failed");return 1;
}
2.3?execlp()
函數原型:
#include <unistd.h>int execlp(const char *file, const char *arg, ... /* (char *) NULL */);
參數:
file
:可執行文件名,會在PATH
環境變量中查找。arg
:第一個參數,通常是程序名。...
:可變參數列表,以NULL
結尾。
例子:
#include <stdio.h>
#include <unistd.h>int main() {printf("Before execlp\n");execlp("ls", "ls", "-l", NULL);// 如果execlp成功,以下代碼不會執行perror("execlp failed");return 1;
}
2.4?execvp()
函數原型:
#include <unistd.h>int execvp(const char *file, char *const argv[]);
參數:
file
:可執行文件名,會在PATH
環境變量中查找。argv
:參數數組,以NULL
結尾。
例子:
#include <stdio.h>
#include <unistd.h>int main() {char *args[] = { "ls", "-l", NULL };printf("Before execvp\n");execvp("ls", args);// 如果execvp成功,以下代碼不會執行perror("execvp failed");return 1;
}
2.5?execle()
函數原型:
#include <unistd.h>int execle(const char *path, const char *arg, ... /* (char *) NULL, char * const envp[] */);
參數:
path
:要執行的可執行文件的路徑。arg
:第一個參數,通常是程序名。...
:可變參數列表,以NULL
結尾。envp
:環境變量數組。
例子:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int main() {char *env[] = { "PATH=/bin", NULL };printf("Before execle\n");execle("/bin/ls", "ls", "-l", NULL, env);// 如果execle成功,以下代碼不會執行perror("execle failed");return 1;
}
2.6 execvpe()
#include <unistd.h>int execvpe(const char *file, char *const argv[], char *const envp[]);
?參數
-
file
:要執行的可執行文件的名稱。如果?file
?中包含斜杠?(/
),則將其視為路徑名,直接嘗試執行。(如果?file
?不包含斜杠,則會在?PATH
?環境變量指定的目錄中查找可執行文件。) -
argv
:參數數組,以?NULL
?結尾。argv[0]
?通常是程序名。 -
envp
:環境變量數組,以?NULL
?結尾。每個環境變量以?"NAME=VALUE"
?的形式表示。
例子:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int main() {// 要執行的程序及其參數char *args[] = { "printenv", "MY_VAR", NULL };// 自定義環境變量char *env[] = { "MY_VAR=HelloWorld", "PATH=/bin:/usr/bin", NULL };printf("Before execvpe\n");// 執行程序if(execvpe("printenv", args, env) == -1) {perror("execvpe failed");exit(1);}// 如果 execvpe 成功,以下代碼不會執行return 0;
}
?
?
?
2.7?execve()(這個上面查庫沒有,要單獨查)
函數原型:
?
?
參數:
pathname
:要執行的可執行文件的路徑。argv
:參數數組,以NULL
結尾。envp
:環境變量數組。
例子:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int main() {char *args[] = { "ls", "-l", NULL };char *env[] = { "PATH=/bin", NULL };printf("Before execve\n");execve("/bin/ls", args, env);// 如果execve成功,以下代碼不會執行perror("execve failed");return 1;
}
?
3. 錯誤處理
大多數exec
函數在成功時不會返回,如果失敗則返回-1,并設置errno
變量。常見的錯誤包括:
- ENOENT:文件不存在。
- EACCES:權限不足。
- ENOEXEC:可執行文件格式錯誤。
例子:
#include <stdio.h>
#include <unistd.h>int main() {if(execl("/bin/ls", "ls", "-l", NULL) == -1) {perror("execl failed");}// 如果execl成功,以下代碼不會執行return 1;
}
?
?
?
?
?
?
?
?
?
?