目錄
引言
1.單進程版程序替換
2.程序替換原理
3.6種替換函數介紹
3.1 函數返回值
3.2 命名理解
3.3 環境變量參數
引言
????????用fork創建子進程后執行的是和父進程相同的程序(但有可能執行不同的代碼分支),我們所創建的所有的子進程,執行的代碼,都是父進程代碼的一部分!如果我們想讓子進程執行新的程序呢???執行全新的代碼和訪問全新的數據,不在和父進程有瓜葛,這時子進程往往要調用一種exec函數以執行另一個程序。
1.單進程版程序替換
execl 介紹:
第一個參數是要替換程序的路徑。
第二個參數是可變參數列表:這里以NULL結束,命令行執行替換程序輸入什么就傳入什么。
代碼示例:將子進程替換為命令行中?ls -a -l?
執行結果:
可以發現子進程id發生進程程序替換時并沒有改變,并且沒有執行代碼中的:
2.程序替換原理
?????????當進程調用一種exec函數時,從外存中將新程序替換掉該進程的用戶空間代碼和數據,所以上面代碼中第二個printf沒有執行。從新程序的啟動例程開始執行。且調用exec并不創建新進程,所以調用exec前后子進程的id并未改變,只是代碼和數據替換。
3.6種替換函數介紹
#include <unistd.h>
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[]);
?
3.1 函數返回值
? ? ? ? 如果進程程序替換成功,不會有返回值,不會執行原程序調用替換后的代碼。失敗有返回值,執行原程序調用替換后的代碼。所以我們不需要接收返回值,可以直接讓原程序退出。
3.2 命名理解
這些函數原型看起來很容易混,但只要掌握了規律就很好記。
l(list):表示參數采用可變參數列表,用來傳遞命令行參數
v(vector):參數采用數據傳遞
p(path):從環境變量PATH中尋找程序
e(env):表示自己維護環境變量
exec調用舉例
#include <unistd.h>
int main()
{char *const argv[] = {"ps", "-ef", NULL};char *const envp[] = {"PATH=/bin:/usr/bin", "TERM=console", NULL};execl("/bin/ps", "ps", "-ef", NULL);// 帶p的,可以使用環境變量PATH,無需寫全路徑execlp("ps", "ps", "-ef", NULL);// 帶e的,需要自己組裝環境變量execle("ps", "ps", "-ef", NULL, envp);execv("/bin/ps", argv);// 帶p的,可以使用環境變量PATH,無需寫全路徑execvp("ps", argv);// 帶e的,需要自己組裝環境變量execve("/bin/ps", argv, envp);exit(0);
}
事實上,只有execve是真正的系統調用,上面6個函數最終都調用 execve,所以execve在man手冊 第2節,其它函數在man手冊第3節。
3.3 環境變量參數
? ? ? ? 環境變量是由父進程傳遞給子進程的,在程序替換時,不會替換掉進程中環境變量,所以要替換的進程環境變量與父進程環境變量是相同的,如果不是傳入自己定義的環境變量,沒有必要調用帶e的程序替換函數。
char* const myenv[]={"MYENY1=111111111","MYENY2=111111111","MYENY3=111111111","MYENY4=111111111",NULL};execle("./mytest","mytest","-a","-b",NULL,myenv);//傳自己定義的環境變量,不是新增,而是覆蓋傳遞
若傳入的環境變量,不是在原來環境變量中新增,而是覆蓋。
mytest.cc:
1 #include <iostream>2 #include <unistd.h>3 4 //程序替換,可以將命令行參數和環境變量,傳遞到被替換的程序的main函數中5 6 int main(int argc,char* argv[],char* env[])7 {8 for(int i =0;i<argc;i++)9 {10 std::cout << i << " -- " << argv[i] << std::endl; 11 }12 13 //打印環境變量 指針數組 環境變量在系統中是全局存在的 父進程是bash的子進程, 子進程環境變量是父進程給的14 for(int i = 0;environ[i]!=NULL;i++)15 {16 std::cout<<i<<" : "<<env[i]<<std::endl;17 }18 19 return 0;20 }
結果:
gitee鏈接
本篇結束!