在進程中運行新代碼
用函數fork創建子進程後,如果希望在當前子進程中運行新的程序,可以調用exec函數執行另一個程序.當進程調用exec函數時,該進程用戶空間資源(正文、數據、堆和棧)完全由新程序替代,新程序則從main函數開始執行.因爲調用exec函數並沒有創建新的進程,所以前後的進程ID並沒有改變,也即內核信息基本不做修改.exec系列函數共有7函數可供使用,這些函數的區別在於:指示新程序的位置是使用路徑還是文件名,如果是使用文件名,則在系統的PATH環境變量所描述的路徑中搜索該程序;在使用參數時使用參數列表的方式還是使用argv[]數組的方式.
1.exec系列函數
函數定義:#include <unistd.h>
int execl(const char *pathname, const char *arg0, ... /* (char *)0 */ );
int execv(const char *pathname, char *const argv[]);
int execle(const char *pathname, const char *arg0, .../* (char *)0, char *const envp[] */ );
int execve(const char *pathname, char *const argv[], char *const envp[]);
int execlp(const char *filename, const char *arg0, ... /* (char *)0 */ );
int execvp(const char *filename, char *const argv[]);
int fexecve(int fd, char *const argv[], char *const envp[]);
返回值:如果執行成功將不返回,否則返回-1,失敗代碼存儲在errno中.
前4個函數取路徑名作爲參數,後兩個是取文件名作爲參數,最後一個是以一個文件描述符作爲參數.
2.函數具體分析
當指定filename作爲參數時:1)如果filename中包含/,則將其視爲路徑名.
2)否則就按PATH環境變量,在它所指的各目錄搜尋可執行文件.
2.1 execl()函數
int execl(const char *pathname, const char *arg0, ... /* (char *)0 */ );execl()函數用來執行參數path字符串所指向的程序,第二個及以後的參數代表執行文件時傳遞的參數列表,最後一個參數必須是空指針以標誌參數列表爲空.
例子1:演示exec()函數的基本使用.
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
int main()
{
pid_t pid;
pid = fork();
if(pid<0)
{
printf("error fork:%m\n");
exit(-1);
}
else if(pid==0)
{
//
execl("/bin/ls","ls","-l","/etc",(char *)0);
}
else
{
printf("parent process\n");
}
return 0;
}
輸出:
2.2 execle()函數
int execle(const char *pathname, const char *arg0, .../* (char *)0, char *const envp[] */ );execle()函數用來執行參數path字符串所指向的程序,第二個及以後的參數代表執行文件時傳遞的參數列表,最後一個參數必須指向一個新的環境變量數組,即新執行程序的環境變量.
例子2:
#include <unistd.h>
int main(int argc, char *argv[], char *env[])
{
execle("/bin/ls","ls","-l", "/etc",(char *)0,env);
return 0;
}
輸出:
2.3 execlp()函數
int execlp(const char *filename, const char *arg0, ... /* (char *)0 */ );execlp()函數會從PATH環境變量所指的目錄中查找文件名爲第一個參數指示的字符串,找到後執行該文件,第二個及以後的參數代表執行文件時傳遞的參數列表,最後一個參數必須是空指針.
例子3:
#include <unistd.h>
int main()
{
execlp("ls", "ls", "-l", "/etc", (char *)0);
return 0;
}
輸出:
2.4 execv()函數
int execv(const char *path, char *const argv[]);execv()函數函數用來執行參數path字符串所指向的程序,第二個爲數組指針維護的程序參數列表,該數組的最後一個成員必須是空指針.
例子4:
#include <unistd.h>
int main()
{
char *argv[] = {"ls", "-l", "/etc", (char *)0};
execv("/bin/ls", argv);
return 0;
}
輸出:
2.5 execvp()函數
int execvp(const char *file, char *const argv[]);execvp()函數會從PATH環境變量所指的目錄中查找文件名爲第一個參數指示的字符串,找到後執行該文件,第二個及以後的參數代表執行文件時傳遞的參數列表,最後一個成員必須是空指針.
例子5:
#include <unistd.h>
int main()
{
char *argv[] = {"ls", "-l", "/etc", (char *)0};
execvp("ls", argv);
return 0;
}
輸出:
幾個函數之間非常相似,沒有找到更好的方法記憶,通過簡單的例子暫時瞭解一下它們之間的不同調用方式.字母聯想也不靠譜:
字母p表示該函數取filename作爲參數,並且用PATH環境變量尋找可執行文件.
字母l表示該函數取一個參數表,它與字母v互斥.
字母v表示該函數取一個argv[]矢量.
字母e表示該函數取envp[]數組.
待續......
筆者:個人能力有限,只是學習參考...讀者若發現文中錯誤,敬請提出.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------勿在浮沙築高臺,靜下心來,慢慢地沉澱---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------