5进程原语:execl(),execlp(),execle(),execv(),execvp(),execvp(),execve()
1.exec族依賴的頭文件
#include<unistd.h>
extern char**environ;
2函數(shù)聲明
//第一個參數(shù):可執(zhí)行程序所在的絕對位置
//第二個參數(shù):可執(zhí)行程序運(yùn)行時所需的參數(shù),這里是一個可變參數(shù),每個參數(shù)之間用逗號分割
//參數(shù)結(jié)束時,最后一個參數(shù)是:NULL
int execl(constchar *path, const char *arg, ...);
?
//注意,這里函數(shù)名加了p,表示調(diào)用了系統(tǒng)的環(huán)境變量中配置的PATH,查看環(huán)境變量命令:Echo $PATH
?
//第一個參數(shù):只需要寫上文件名即可,不用寫全路徑,后面的參數(shù)和上面的參數(shù)相同
int execlp(constchar *file, const char *arg, ...);
?
//第一個參數(shù):全路徑
//envp[],表示傳遞的是環(huán)境變量的數(shù)組
int execle(constchar *path, const char *arg,
????????????????? ..., char * const envp[]);
?
//這個和第一個exec函數(shù)區(qū)別是,這里的參數(shù)不是可變參數(shù)了,而是通過一個傳遞一個數(shù)組的方式進(jìn)行傳遞進(jìn)去。
int execv(constchar *path, char *const argv[]);
?
//execvp和execv的區(qū)別僅僅是文件名和路徑的區(qū)別。
int execvp(constchar *file, char *const argv[]);
?
//這時候傳遞環(huán)境變量
int execvpe(constchar *file, char *const argv[],
?????????????????? char *const envp[]);
?
3.注意:
?? A:這些函數(shù)如果調(diào)用成功則加載新的程序從啟動代碼開始執(zhí)行,不再返回,如果調(diào)用出錯則返回-1,所以exec函數(shù)只有出錯的返回值而沒有成功的返回值。
?? B: 這些函數(shù)原型看起來很容易混,但只要掌握了規(guī)律就很好記。不帶字母p(表示
path)的exec函數(shù)第一個參數(shù)必須是程序的相對路徑或絕對路徑,例如“/bin/ls”或“./
a.out”,而不能是“ls”或“a.out”。對于帶字母p的函數(shù):
如果參數(shù)中包含/,則將其視為路徑名。
否則視為不帶路徑的程序名,在PATH環(huán)境變量的目錄列表中搜索這個程序。
帶有字母l(表示list)的exec函數(shù)要求將新程序的每個命令行參數(shù)都當(dāng)作一個參數(shù)傳
給它,命令行參數(shù)的個數(shù)是可變的,因此函數(shù)原型中有…,…中的最后一個可變參數(shù)應(yīng)該是
NULL,起sentinel的作用。對于帶有字母v(表示vector)的函數(shù),則應(yīng)該先構(gòu)造一個指向
各參數(shù)的指針數(shù)組,然后將該數(shù)組的首地址當(dāng)作參數(shù)傳給它,數(shù)組中的最后一個指針也應(yīng)該
是NULL,就像main函數(shù)的argv參數(shù)或者環(huán)境變量表一樣。
C:對于以e(表示environment)結(jié)尾的exec函數(shù),可以把一份新的環(huán)境變量表傳給它,其他exec函數(shù)仍使用當(dāng)前的環(huán)境變量表執(zhí)行新程序。
??? D:exec調(diào)用舉例如下:
char *const ps_argv[] ={"ps","-o", "pid,ppid,pgrp,session,tpgid,comm", NULL};
char *const ps_envp[]={"PATH=/bin:/usr/bin", "TERM=console", NULL};
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);
E: 事實(shí)上,只有execve是真正的系統(tǒng)調(diào)用,其它五個函數(shù)最終都調(diào)用execve,所以execve在man手冊第2節(jié),其它函數(shù)在man手冊第3節(jié)。這些函數(shù)之間的關(guān)系如下圖所示。
?
4.案例說明:
運(yùn)行結(jié)果:
5. 由于exec函數(shù)只有錯誤返回值,只要返回了一定是出錯了,所以不需要判斷它的
返回值,直接在后面調(diào)用perror即可。注意在調(diào)用execlp時傳了兩個“ps”參數(shù),第一
個“ps”是程序名,execlp函數(shù)要在PATH環(huán)境變量中找到這個程序并執(zhí)行它,而第二
個“ps”是第一個命令行參數(shù),execlp函數(shù)并不關(guān)心它的值,只是簡單地把它傳給ps程
序,ps程序可以通過main函數(shù)的argv[0]取到這個參數(shù)。
調(diào)用exec后,原來打開的文件描述符仍然是打開的。利用這一點(diǎn)可以實(shí)現(xiàn)I/O重定向。
先看一個簡單的例子,把標(biāo)準(zhǔn)輸入轉(zhuǎn)成大寫然后打印到標(biāo)準(zhǔn)輸出:
運(yùn)行結(jié)果:
運(yùn)行結(jié)果:
分析:
wrapper程序?qū)⒚钚袇?shù)當(dāng)作文件名打開,將標(biāo)準(zhǔn)輸入重定向到這個文件,然后調(diào)用
exec執(zhí)行upper程序,這時原來打開的文件描述符仍然是打開的,upper程序只負(fù)責(zé)從標(biāo)準(zhǔn)輸入讀入字符轉(zhuǎn)成大寫,并不關(guān)心標(biāo)準(zhǔn)輸入對應(yīng)的是文件還是終端。
??? exec族
l 命令行參數(shù)列表
p 搜素file時使用path變量
v 使用命令行參數(shù)數(shù)組
e 使用環(huán)境變量數(shù)組,不使用進(jìn)程原有的環(huán)境變量,設(shè)置新加載程序運(yùn)行的環(huán)境變量
?
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的5进程原语:execl(),execlp(),execle(),execv(),execvp(),execvp(),execve()的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。