用fork
建立子程序後執行的是和父程序相同的程式(但有可能執行不同的**分支),子程序往往要呼叫一種exec函式以執行另乙個程式。
當程序呼叫一種exec
函式時,該程序的使用者空間**和資料完全被新程式替換,從新程式的啟動例程開始執行。
呼叫exec並不建立新程序,所以呼叫exec前後該程序的id並未改變。
以exec開頭的函式,統稱exec函式:
#include
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 execve(const
char *path, char *const argv, char *const envp);
這些函式如果呼叫成功則載入新的程式從啟動**開始執行,不再返回,如果呼叫出錯則返回-1,所以exec
函式只有出錯的返回值而沒有成功的返回值。exec族函式各函式分析及記憶:不帶字母p
(表示path
)的exec函式第乙個引數必須是程式的相對路徑或絕對路徑,例如「/bin/ls
」或「./a.out」,而不能是「ls
」或「a.out
」。
對於帶字母p
的函式:
如果引數中包含/
,則將其視為路徑名。
否則視為不帶路徑的程式名,在path
環境變數的目錄列表中搜尋這個程式。
帶有字母l
(表示list
)的exec函式要求將新程式的每個命令列引數都當作乙個引數傳給它,命令列引數的個數是可變的,因此函式原型中有…
,…
中的最後乙個可變引數應該是null
,起sentinel(哨兵)的作用。
對於帶有字母v
(表示vector
)的函式,則應該先構造乙個指向各引數的指標陣列,然後將該陣列的首位址當作引數傳給它,陣列中的最後乙個指標也應該是null
,就像main函式的argv
引數或者環境變數表一樣。
對於以e
(表示environment
)結尾的exec函式,可以把乙份新的環境變數表傳給它,其他exec函式仍使用當前的環境變數表執行新程式。
exec呼叫舉例如下:
char *const ps_argv =;
char *const ps_envp =;
execl("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", null);
execv("/bin/ps", ps_argv);
execle("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", null, ps_envp);
execve("/bin/ps", ps_argv, ps_envp);
execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", null);
execvp("ps", ps_argv);
事實上,只有execve
是真正的系統呼叫,其它五個函式最終都呼叫execve
,這些函式之間的關係如下圖所示:
乙個完整的例子:
#include
#include
int main(void)
由於exec函式只有錯誤返回值,只要返回了一定是出錯了,所以不需要判斷它的返回值,直接在後面呼叫perror
即可。注意在呼叫execlp時傳了兩個「ps」引數,第乙個「ps」是程式名,execlp函式要在path環境變數中找到這個程式並執行它,而第二個「ps」是第乙個命令列引數,execlp函式並不關心它的值,只是簡單地把它傳給ps程式,ps程式可以通過main函式的argv[0]取到這個引數。
實現i/o重定向
呼叫exec後,原來開啟的檔案描述符仍然是開啟的。利用這一點可以實現i/o重定向。
先看乙個簡單的例子,把標準輸入轉成大寫然後列印到標準輸出:
例大小寫轉換原始碼upper.c
:
/* upper.c */
#include
int main(void)
return
0;}
#include
#include
#include
#include
int main(int argc, char *argv)
fd = open(argv[1], o_rdonly);
if(fd<0)
dup2(fd, stdin_fileno);
close(fd);
execl("./upper", "upper", null);
perror("exec ./upper");
exit(1);}
學習資料來自邢文鵬老師
Linux 程序 exec函式族
其他exec 函式 練習拓展dup2 dup to 函式 一 exec的簡介 1.fork建立程序後執行的是和父程序相同的程式 但有可能執行不同的 分支 子程序往往要呼叫一種exec函式執行另一種程式。當程序呼叫一種exec函式時,該程序的使用者空間 和資料完全被新程式替換,從新程式的啟動例程開始執...
Linux程序 exec族函式
1 為什麼要使用exec族函式 當我們fork乙個子程序就是為了執行乙個新的程式,此時可以呼叫exec族函式,執行已經編譯好的可執行程式或者linux自帶的ls cd等命令。2 exec族函式如何使用 函式原型 include extern char environ intexecl const c...
Linux程序之exec族函式
fork函式建立新程序後,經常會在新程序中呼叫exec函式去執行另外乙個程式。當程序呼叫exec函式時,該程序被完全替換為新程式。因為呼叫exec函式並不建立新程序,所以前後程序的id並沒有改變。原創鏈結 include include include 函式原型 int execl const ch...