1、exec函數說明
fork()函數通過系統調用創建一個與原來進程(父進程)幾乎完全相同的進程(子進程是父進程的副本,它將獲得父進程數據空間、堆、棧等資源的副本。注意,子進程持有的是上述存儲空間的“副本”,這意味着父子進程不共享這些存儲空間。linux將複製父進程的地址空間內容給子進程,因此,子進程由了獨立的地址空間。),也就是這兩個進程做完全相同的事。
在fork後的子進程中使用exec函數族,可以裝入和運行其它程序(子進程替換原有進程,和父進程做不同的事)。
exec函數族可以根據指定的文件名或目錄名找到可執行文件,並用它來取代原調用進程的數據段、代碼段和堆棧段。在執行完後,原調用進程的內容除了進程號外,其它全部被新程序的內容替換了。另外,這裏的可執行文件既可以是二進制文件,也可以是Linux下任何可執行腳本文件。
2.在Linux中使用exec函數族主要有一下兩種情況
當進程認爲自己不能再爲系統和用戶做出任何貢獻時,就可以調用任何exec函數族讓自己重生;如果一個進程想執行另外一個程序,那麼它就可以調用fork函數新建一個進程,然後調用任何一個exec函數使子進程重生;
exec函數族聲明如下:
int execl(const char *path, const char *arg, …)
int execv(const char *path, char *const argv[])
int execle(const char *path, const char *arg, …, char *const envp[])
int execve(const char *path, char *const argv[], char *const envp[])
int execlp(const char *file, const char *arg, …)
int execvp(const char *file, char *const argv[])
可見,使用execle和execve可以自己向執行進程傳遞環境變量,但不會繼承Shell進程的環境變量,而其他四個exec函數則繼承Shell進程的所有環境變量。
1、execl用法如下:
#include <stdio.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
printf("start to execl.\n");
if(execl("/bin/ls","ls",NULL) < 0)
{
perror("Fail to execl");
return -1;
}
printf("end of execl.\n");
return 0;
}
結果如下:
execl("/bin/ls",“ls”,NULL):
第一個參數是可執行文件的絕對路徑,第二個參數是可執行文件的名稱
2、execlp
#include <stdio.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
printf("start to execl.\n");
if(execlp("ls","ls","-l",NULL) < 0)
{
perror("Fail to execl");
return -1;
}
printf("end of execl.\n");
return 0;
}
execlp(“ls”,“ls”,"-l",NULL):
第一個參數是可執行文件的相對路徑,第二個參數是可執行文件的名字,第三個參數是帶參數的可執行文件。衆所周知,ls是查看當前目錄下所有的文件,ls -l是列出長數據串,顯示出文件的屬性與權限等數據信息。
3、execle
利用函數execle,將環境變量添加到新建的子進程中去。
#include <unistd.h>
#include <stdio.h>
int main()
{
/*命令參數列表,必須以 NULL 結尾*/
char *envp[]={"PATH=/tmp","USER=sun",NULL};
if(fork()==0){
/*調用 execle 函數,注意這裏也要指出 env 的完整路徑*/
if(execle("/usr/bin/env","env",NULL,envp)<0)
// if(execle("./test","test",NULL,envp)<0)
//但是我這裏使用了相對路徑也是可以的
{
perror("execle error!");
return -1 ;
}
}
return 0 ;
}