標籤:execle函數 execlp函數 execv函數 execve和execvp函數
摘要:本文主要講述如何在進程中運行新代碼,以及exec系列函數的基本使用方法.
在進程中運行新代碼
用函數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字串所指向的程式,第二個及以後的參數代表執行檔案時傳遞的參數列表,最後一個參數必須是null 指標以標誌參數列表為空白.
例子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環境變數所指的目錄中尋找檔案名稱為第一個參數指示的字串,找到後執行該檔案,第二個及以後的參數代表執行檔案時傳遞的參數列表,最後一個參數必須是null 指標.
例子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字串所指向的程式,第二個為數組指標維護的程式參數列表,該數組的最後一個成員必須是null 指標.
例子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環境變數所指的目錄中尋找檔案名稱為第一個參數指示的字串,找到後執行該檔案,第二個及以後的參數代表執行檔案時傳遞的參數列表,最後一個成員必須是null 指標.
例子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[]數組.
待續......
筆者:個人能力有限,只是學習參考...讀者若發現文中錯誤,敬請提出.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------勿在浮沙築高台,靜下心來,慢慢地沉澱---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
在進程中運行新代碼