系統編程-exec函數族的使用
fork
創建子進程後執行的是和父進程相同的程序(但有可能執行不同的代碼分支),子進程往往要調用一種exec
函數以執行另一個程序。當進程調用一種exec
函數時,該進程的用戶控件代碼和數據完全被新程序替換,從新程序的啓動例程開始執行。執行exec
並不創建新進程,所以調用exec前後該進程的id並未改變。
將當前進程的.tex
t、.data
替換爲所要加載的程序的.text
、.data
,然後讓進程從新的.text
第一條指令開始執行,但進程ID
不變,換核不換殼。
//該函數通常用來調用用戶自定義的可執行程序
int execl(const char *path, const char *arg, ...);
//該函數通常用來調用系統程序。如:ls、date、cp、cat等命令。
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 execve(const char *path, char *const argv[], char *const envp[]);
“l”表示參數以列表的形式表示;
“v”表示參數以數組的形式表示;
“p”表示在PATH中搜索執行文件;
有“p”可以省去絕對路徑
“e”表示可附加環境參數。
注意的地方有:
1、參數以NULL
或者0
結尾;
2、exec函數族執行成功後不會返回,執行失敗會返回 -1
,錯誤代碼存放在errno
中
3、可能的幾種錯誤有,找不到文件或路徑,errno
爲ENOENT
;數組argv
或envp
沒有以NULL
或者0
結尾,errno
爲EFAULT
;沒有對執行文件的執行權限,errno
爲EACCESS
;
測試代碼:
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
int main(int argc,char** argv){
char* envp[] = {"PATH=/usr/bin","USER=admin",0};
char* argv_execv[] = {"echo","exec on execv",0};
char* argv_execvp[] = {"echo","exec on execvp",0};
char* argv_execve[] = {"echo","exec on execve",0};
if(fork() == 0){
if(execl("/bin/echo","echo","execut by execl",NULL) < 0){
perror("error on execl");
}
}
if(fork() == 0){
if(execlp("echo","echo","exec by execlp",NULL) < 0 )
perror("error execlp");
}
if(fork() == 0){
if(execle("/bin/echo","echo","execut by execle",NULL,envp) < 0){
perror("error on execle");
}
}
if(fork() == 0){
if(execv("/bin/echo",argv_execv) < 0){
perror("error on execv");
}
}
if(fork() == 0){
if(execvp("echo",argv_execvp) < 0)
{
perror("error on execvp");
}
}
if(fork() == 0){
if(execve("/bin/echo",argv_execve,envp) < 0)
{
perror("error on execve");
}
}
return 0;
}
運行結果: