文章目錄
- 進程替換
- exec 函數族使用說明
- 查看命令的路徑 which
- 測試 execl
- 測試 execlp
- 測試 execv
- 測試 execvp
進程替換
概述
在 Windows 平臺下,我們可以通過雙擊運行可執行程序,讓這個可執行程序成為一個進程;而在 Linux 平臺,我們可以通過 ./ 運行,讓一個可執行程序成為一個進程。
但是,如果我們本來就運行著一個程序(進程),我們如何在這個進程內部啟動一個外部程序,由內核將這個外部程序讀入內存,使其執行起來成為一個進程呢?這里我們通過 exec 函數族實現。
exec 函數族,顧名思義,就是一簇函數,在 Linux 中,并不存在 exec() 函數,exec 指的是一組函數,一共有 6 個:
#include <unistd.h>
extern char **environ;int execl(const char *path, const char *arg, .../* (char *) NULL */);
int execlp(const char *file, const char *arg, ... /* (char *) NULL */);
int execle(const char *path, const char *arg, .../*, (char *) NULL, 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[]);int execve(const char *filename, char *const argv[], char *const envp[]);
其中只有 execve() 是真正意義上的系統調用,其它都是在此基礎上經過包裝的庫函數。
exec 函數族的作用是根據指定的文件名或目錄名找到可執行文件,并用它來取代調用進程的內容,換句話說,就是在調用進程內部執行一個可執行文件。
進程調用一種 exec 函數時,該進程完全由新程序替換,而新程序則從其 main 函數開始執行。因為調用 exec 并不創建新進程,所以前后的進程 ID (當然還有父進程號、進程組號、當前工作目錄……)并未改變。exec 只是用另一個新程序替換了當前進程的正文、數據、堆和棧段(進程替換)。
exec 函數族使用說明
exec 函數族的 6 個函數看起來似乎很復雜,但實際上無論是作用還是用法都非常相似,只有很微小的差別。
補充說明:
l(list) | 參數地址列表,以空指針結尾 |
---|---|
v(vector) | 存有各參數地址的指針數組的地址 |
p(path) | 按 PATH 環境變量指定的目錄搜索可執行文件 |
e(environment) | 存有環境變量字符串地址的指針數組的地址 |
exec 函數族與一般的函數不同,exec 函數族中的函數執行成功后不會返回,而且,exec 函數族下面的代碼執行不到。只有調用失敗了,它們才會返回 -1,失敗后從原程序的調用點接著往下執行。
查看命令的路徑 which
which 命令
which ls
測試 execl
#include <stdio.h>
#include <string.h>
#include <stdlib.h> #include <unistd.h>int test01()
{//執行 ls -l /home//參數一: 可執行文件的路徑//參數二: 可執行文件的名字//參數三: 選項//參數四: 參數//最后一個參數一定要是是NULLexecl("/bin/ls", "ls", "-l", "/home", NULL);printf("hello world\n");return 0;}
測試 execlp
int test01()
{//執行 ls -l /home//參數一: 可執行文件//參數二: 可執行文件的名字//參數三: 選項//參數四: 參數//最后一個參數一定要是是NULLexecl("ls", "ls", "-l", "/home", NULL);printf("hello world\n");return 0;}
測試 execv
int test01()
{char *const argv[] = {"ls", "-l", "/home", NULL};//執行 ls -l /home//參數一: 可執行文件//參數二: 可執行文件的名字execv("/bin/ls", argv);printf("hello world\n");return 0;
}
測試 execvp
int test01()
{char *const argv[] = {"ls", "-l", "/home", NULL};//執行 ls -l /home//參數一: 可執行文件//參數二: 可執行文件的名字execvp("ls",argv);printf("hello world\n");return 0;
}