日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

12.Linux:exec函数族

發(fā)布時(shí)間:2025/3/21 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 12.Linux:exec函数族 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

(1)exec函數(shù)說明


fork函數(shù)是用于創(chuàng)建一個(gè)子進(jìn)程該子進(jìn)程幾乎是父進(jìn)程的副本,而有時(shí)我們希望子進(jìn)程去執(zhí)行另外的程序exec函數(shù)族就提供了一個(gè)在進(jìn)程中啟動(dòng)另一個(gè)程序執(zhí)行的方法。它可以根據(jù)指定的文件名或目錄名在磁盤上找到可執(zhí)行文件,并用它來取代原調(diào)用進(jìn)程的數(shù)據(jù)段、代碼段和堆棧段,在執(zhí)行完之后,原調(diào)用進(jìn)程(該調(diào)用函數(shù)族的進(jìn)程)的內(nèi)容除了進(jìn)程號(hào)外,其他全部被新程序的內(nèi)容替換了。另外,這里的可執(zhí)行文件既可以是二進(jìn)制文件,也可以是Linux下任何可執(zhí)行腳本文件(/bin/sh 解釋執(zhí)行shell腳本)。


(2)在Linux中使用exec函數(shù)族主要有以下兩種情況:


a. 當(dāng)進(jìn)程認(rèn)為自己不能再為系統(tǒng)和用戶做出任何貢獻(xiàn)時(shí),就可以調(diào)用任何exec 函數(shù)族讓自己重生,即自己執(zhí)行新程序
b.如果一個(gè)進(jìn)程想執(zhí)行另一個(gè)程序,那么它就可以調(diào)用fork函數(shù)新建一個(gè)進(jìn)程,然后子進(jìn)程調(diào)用exec函數(shù)使子進(jìn)程重生。
?


(3)exec函數(shù)族語法


實(shí)際上,在Linux中并沒有exec函數(shù),而是有6個(gè)以exec開頭的函數(shù)族,下表列舉了exec函數(shù)族的6個(gè)成員函數(shù)的語法。
所需頭文件:?#include <unistd.h>
函數(shù)說明:?執(zhí)行文件
函數(shù)原型:

int execl(const char *path, const char *arg, ...) int execv(const char *path, char *const argv[]) int execle(const char *path, const char *arg, ..., char *const envp[]) int execve(const char *path, char *const argv[], char *const envp[]) int execlp(const char *file, const char *arg, ...) int execvp(const char *file, char *const argv[])

函數(shù)返回值:成功 -> 函數(shù)不會(huì)返回,出錯(cuò) -> 返回-1,失敗原因記錄在error中。
這6個(gè)函數(shù)在函數(shù)名和使用語法的規(guī)則上都有細(xì)微的區(qū)別,下面就可執(zhí)行文件查找方式、參數(shù)表傳遞方式及環(huán)境變量這幾個(gè)方面進(jìn)行比較說明。


①???查找方式:上表其中前4個(gè)函數(shù)的查找方式都是完整的文件目錄路徑,而最后2個(gè)函數(shù)(也就是以p結(jié)尾的兩個(gè)函數(shù))可以只給出文件名,系統(tǒng)就會(huì)自動(dòng)從環(huán)境變量“$PATH”所指出的路徑中進(jìn)行查找。



②???參數(shù)傳遞方式:exec函數(shù)族的參數(shù)傳遞有兩種方式,一種是逐個(gè)列舉的方式,而另一種則是將所有參數(shù)整體構(gòu)造成指針數(shù)組進(jìn)行傳遞。
在這里參數(shù)傳遞方式是以函數(shù)名的第5位字母來區(qū)分的,字母為“l(fā)”(list)的表示逐個(gè)列舉的方式,字母為“v”(vertor)的表示將所有參數(shù)整體構(gòu)造成指針數(shù)組傳遞,然后將該數(shù)組的首地址當(dāng)做參數(shù)傳給它,數(shù)組中的最后一個(gè)指針要求是NULL。讀者可以觀察execl、execle、execlp的語法與execv、execve、execvp的區(qū)別。



③??環(huán)境變量:exec函數(shù)族使用了系統(tǒng)默認(rèn)的環(huán)境變量,也可以傳入指定的環(huán)境變量。這里以“e”(environment)結(jié)尾的兩個(gè)函數(shù)execle、execve就可以在envp[]中指定當(dāng)前進(jìn)程所使用的環(huán)境變量替換掉該進(jìn)程繼承的所以環(huán)境變量。



PATH環(huán)境變量說明:PATH環(huán)境變量包含了一張目錄表,系統(tǒng)通過PATH環(huán)境變量定義的路徑搜索執(zhí)行碼,PATH環(huán)境變量定義時(shí)目錄之間需用用“:”分隔,以“.”號(hào)表示結(jié)束。PATH環(huán)境變量定義在用戶的.profile或.bash_profile中,下面是PATH環(huán)境變量定義的樣例,此PATH變量指定在“/bin”、“/usr/bin”和當(dāng)前目錄三個(gè)目錄進(jìn)行搜索執(zhí)行碼。
PATH=/bin:/usr/bin:.
export $PATH



進(jìn)程中的環(huán)境變量說明:在Linux中,Shell進(jìn)程是所有執(zhí)行碼的父進(jìn)程當(dāng)一個(gè)執(zhí)行碼執(zhí)行時(shí),Shell進(jìn)程會(huì)fork子進(jìn)程然后調(diào)用exec函數(shù)去執(zhí)行執(zhí)行碼。Shell進(jìn)程堆棧中存放著該用戶下的所有環(huán)境變量,使用execl、execv、execlp、execvp函數(shù)使執(zhí)行碼重生時(shí),Shell進(jìn)程會(huì)將所有環(huán)境變量復(fù)制給生成的新進(jìn)程;而使用execle、execve時(shí)新進(jìn)程不繼承任何Shell進(jìn)程的環(huán)境變量,而由envp[]數(shù)組自行設(shè)置環(huán)境變量。



exec函數(shù)族關(guān)系
第4位統(tǒng)一為:exec
第5位
l:參數(shù)傳遞為逐個(gè)列舉方式
execl、execle、execlp
v:參數(shù)傳遞為構(gòu)造指針數(shù)組方式
execv、execve、execvp
第6位
e:可傳遞新進(jìn)程環(huán)境變量
execle、execve
p:可執(zhí)行文件查找方式為文件名
execlp、execvp


事實(shí)上,這6個(gè)函數(shù)中真正的系統(tǒng)調(diào)用只有execve,其他5個(gè)都是庫函數(shù),它們最終都會(huì)調(diào)用execve這個(gè)系統(tǒng)調(diào)用,調(diào)用關(guān)系如下圖12-11所示:

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖12-11 exec函數(shù)族關(guān)系圖
(7)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);


請注意exec函數(shù)族形參展開時(shí)的前兩個(gè)參數(shù),第一個(gè)參數(shù)是帶路徑的執(zhí)行碼(execlp、execvp函數(shù)第一個(gè)參數(shù)是無路徑的,系統(tǒng)會(huì)根據(jù)PATH自動(dòng)查找然后合成帶路徑的執(zhí)行碼),第二個(gè)是不帶路徑的執(zhí)行碼,執(zhí)行碼可以是二進(jìn)制執(zhí)行碼和Shell腳本。


(8)exec函數(shù)族使用注意點(diǎn)
在使用exec函數(shù)族時(shí),一定要加上錯(cuò)誤判斷語句。因?yàn)?strong>exec很容易執(zhí)行失敗,其中最常見的原因有:
① ? ?找不到文件或路徑,此時(shí)errno被設(shè)置為ENOENT。
② ? ?數(shù)組argv和envp忘記用NULL結(jié)束,此時(shí)errno被設(shè)置為EFAULT。
③ ? ?沒有對應(yīng)可執(zhí)行文件的運(yùn)行權(quán)限,此時(shí)errno被設(shè)置為EACCES。



(9)exec后新進(jìn)程保持原進(jìn)程以下特征
? ? ?環(huán)境變量(使用了execle、execve函數(shù)則不繼承環(huán)境變量);
? ? ?進(jìn)程ID和父進(jìn)程ID;
? ? ?實(shí)際用戶ID和實(shí)際組ID;
? ? ?附加組ID;
? ? ?進(jìn)程組ID;
? ? ?會(huì)話ID;
? ? ?控制終端;
? ? ?當(dāng)前工作目錄;
? ? ?根目錄;
? ? ?文件權(quán)限屏蔽字;
? ? ?文件鎖;
? ? ?進(jìn)程信號(hào)屏蔽;
? ? ?未決信號(hào);
? ? ?資源限制;
? ? ?tms_utime、tms_stime、tms_cutime以及tms_ustime值。
對打開文件的處理與每個(gè)描述符的exec關(guān)閉標(biāo)志值有關(guān),進(jìn)程中每個(gè)文件描述符有一個(gè)exec關(guān)閉標(biāo)志(FD_CLOEXEC),若此標(biāo)志設(shè)置,則在執(zhí)行exec時(shí)關(guān)閉該描述符,否則該描述符仍打開。除非特地用fcntl設(shè)置了該標(biāo)志,否則系統(tǒng)的默認(rèn)操作是在exec后仍保持這種描述符打開,利用這一點(diǎn)可以實(shí)現(xiàn)I/O重定向。



(10)execlp函數(shù)舉例

execlp.c源代碼如下:

#include <stdio.h> #include <unistd.h>int main() {if(fork()==0){if(execlp("/usr/bin/env","env",NULL)<0){perror("execlp error!");return -1 ;}}return 0 ; }

編譯 gcc execlp.c –o execlp。
執(zhí)行 ./execlp,執(zhí)行結(jié)果如下:

HOME=/home/test DB2DB=test SHELL=/bin/bash……

由執(zhí)行結(jié)果看出,execlp函數(shù)使執(zhí)行碼重生時(shí)繼承了Shell進(jìn)程的所有環(huán)境變量,其他三個(gè)不以e結(jié)尾的函數(shù)同理。
(11)execle函數(shù)舉例
利用函數(shù)execle,將環(huán)境變量添加到新建的子進(jìn)程中去。
execle.c源代碼如下:

#include <unistd.h> #include <stdio.h>int main() {/*命令參數(shù)列表,必須以 NULL 結(jié)尾*/char *envp[]={"PATH=/tmp","USER=sun",NULL};if(fork()==0){/*調(diào)用 execle 函數(shù),注意這里也要指出 env 的完整路徑*/if(execle("/usr/bin/env","env",NULL,envp)<0){perror("execle error!");return -1 ;}}return 0 ; }

編譯:gcc execle.c –o execle。執(zhí)行./execle,執(zhí)行結(jié)果如下:

PATH=/tmp USER=sun

可見,使用execle和execve可以自己向執(zhí)行進(jìn)程傳遞環(huán)境變量,但不會(huì)繼承Shell進(jìn)程的環(huán)境變量,而其他四個(gè)exec函數(shù)則繼承Shell進(jìn)程的所有環(huán)境變量。

總結(jié)

以上是生活随笔為你收集整理的12.Linux:exec函数族的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。