linux下的exec函數不是單一的函數,而是一個函數組,分別為:
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[]);
可以看到這個函數組的函數名都是有exec和添加l、v、p、e這四個字母的組合而來。
字母l代表list,表示該函數取一個參數表,即要求將新程式的每個命令列參數都說明為一個單獨的參數,必須以(char*)0結尾;
字母v代表vector,表示該函數取一個argv[]向量,即要求先構造一個指向各個參數的數組指標,然後將該數組地址作為這個exec函數的參數;
字母p代表path,表示該函數取filename作為參數,並且使用PATH環境變數尋找可執行檔;
字母e代表environ,表示該函數取一個envp[]數組,而不使用當前環境。
這裡,字母l和v互斥,即不能同時出現在exec函數中。
exec函數最為常見的是調用替換執行可執行檔,諸如:
execl("/bin/echo","echo", "executed by execl", NULL)中的echo;
execl("/bin/ls", "ls","/azuo", "-la", (char *)0 )中的ls;
execlp("echo", "echo","executed by execlp", NULL)中的echo;
但是另外一種執行方式是調用執行shell指令碼。
有兩種方法使用exec函數組調用shell指令碼:
方法一:使用execl函數,這種方法與execl("/bin/echo", "echo", "executed byexecl", NULL)中的echo 類似。它直接使用可執行檔來執行指令碼。
將/bin/echo換為了/bin/sh或/bin/bash。
這樣我們可以使用如下函數調用t.sh指令碼
execle("/bin/sh","sh","t.sh",NULL,NULL);
可以向t.sh指令碼傳入參數,這裡省略。
方法二:使用execle函數
char* env[]={"envargv=\"i'm inenvironment! you see me.\"",NULL};
execle("t.sh","nouse","i'min argv!",NULL,env);
使用execle函數,也可以向shell指令碼傳遞參數,在指令碼中使用$0,$1$2等等來進行引用,$1為第一個參數,這個與main函數的argv類似。
這裡execle函數發現pathname參數並不是由串連編輯器產生的機器可執行檔,則認為該檔案是一個shell指令碼,於是試圖調用/bin/sh,並以filename作shell的輸入。
與上一個方法不同的是,execl函數運行shell指令碼即使用可執行檔,不要求t.sh有執行許可權。而execle函數則要求使用者擁有被調用的shell指令碼的執行許可權,否則會調用失敗,且通常不會提示Permission denied錯誤資訊。所以在使用execle調用shell指令碼時要確保指令碼自身擁有執行許可權。
這樣的差別和終端下類似:
終端下使用sh t.sh 不需要執行許可權而./t.sh就需要了。
以下為一組具體執行個體:
t.sh指令碼:
#!/bin/bashif [ -n "$envargv" ]; then echo "you can use the var of env." echo "the vat in env:$envargv" echo "the var in argv:$1"fiecho "er,you see me again."
測試主程式:
tryexec.程式
#include <unistd.h>#include<string.h>#include <stdio.h>int main(int argc,char** argv){ char par[10]={0}; strcpy(par,argv[1]); if(!strcmp(par,"execl")) { printf("******************execl*****************\n"); execl( "/bin/cat","cat","/home/gs/exec.txt",NULL); } if(!strcmp(par,"execle1")) { printf("**************call shell script (1)*****************\n"); execle( "/bin/sh","sh","t.sh",NULL,NULL); } if(!strcmp(par,"execle2")) { printf("**************call shell script(2)*****************\n"); char* env[]={"envargv=\"i'm in environment! you see me.\"",NULL}; execle("t.sh","nouse","i'm in argv!",NULL,env); } return 0;}
運行結果如下:
root@ubuntu:/home/gs/linuxapiusage# gcc tryexec.croot@ubuntu:/home/gs/linuxapiusage# ./a.out execl******************execl*****************hello,you see me.root@ubuntu:/home/gs/linuxapiusage# ./a.out execle1**************call shell script (1)*****************er,you see me again.root@ubuntu:/home/gs/linuxapiusage# ./a.out execle2 此處沒有t.sh的執行許可權**************call shell script(2)***************** root@ubuntu:/home/gs/linuxapiusage# ./a.out execle2 增加執行許可權 chmod +x t.sh**************call shell script(2)*****************you can use the var of env.the vat in env:"i'm in environment! you see me."the var in argv:i'm in argv!er,you see me again.
以上為execl和execle來調用的shell指令碼,當然使用execv 和 execve也可以,只不過是參數傳入格式的問題了。
更多資訊請參考:
exec相關
http://man7.org/linux/man-pages/man3/exec.3.html
或linux下man exec
exec函數組介紹
http://blog.csdn.net/fisher_jiang/article/details/5608399
以及APUE 8.10
本人享有部落格文章的著作權,轉載請標明出處http://blog.csdn.net/baidu20008