博客專(zhuān)欄

EEPW首頁(yè) > 博客 > 嵌入式Linux:子進(jìn)程執(zhí)行新程序

嵌入式Linux:子進(jìn)程執(zhí)行新程序

發(fā)布人:美男子玩編程 時(shí)間:2024-10-17 來(lái)源:工程師 發(fā)布文章

在 Linux 中,子進(jìn)程在創(chuàng)建后可以通過(guò) exec 系列系統(tǒng)調(diào)用執(zhí)行一個(gè)全新的程序。這種情況下,子進(jìn)程會(huì)替換原有的代碼和數(shù)據(jù)段,運(yùn)行一個(gè)新的可執(zhí)行程序,但它的進(jìn)程 ID(PID)保持不變。exec 系列調(diào)用包括多個(gè)變體,常見(jiàn)的有 execl()、execv()、execle()、execve() 等,它們的主要區(qū)別在于參數(shù)傳遞方式不同。


子進(jìn)程執(zhí)行新程序的流程如下:

  • 創(chuàng)建子進(jìn)程使用 fork() 創(chuàng)建子進(jìn)程。

  • 調(diào)用 exec在子進(jìn)程中調(diào)用 exec 執(zhí)行新程序。

  • 替換子進(jìn)程的內(nèi)存映像exec 會(huì)替換子進(jìn)程的整個(gè)內(nèi)存空間,包括代碼段、數(shù)據(jù)段、堆棧等,只保留進(jìn)程的 PID 和一些特定屬性。

  • 父進(jìn)程繼續(xù)執(zhí)行父進(jìn)程保持不變,繼續(xù)執(zhí)行它的代碼,直到調(diào)用 wait() 等待子進(jìn)程結(jié)束。


exec 系列函數(shù)通過(guò)不同的方式傳遞參數(shù)和環(huán)境變量,能夠?qū)崿F(xiàn)靈活的程序替換。具體函數(shù)如下:

  • execve() 是最基礎(chǔ)的調(diào)用,允許自定義環(huán)境變量和參數(shù)。

  • execl() 和 execv() 提供了簡(jiǎn)化接口,execl() 使用可變參數(shù),execv() 使用參數(shù)數(shù)組。

  • execlp() 和 execvp() 可以根據(jù) PATH 環(huán)境變量搜索程序。

  • execle() 和 execvpe() 提供自定義環(huán)境變量的支持。


1


execve()

execve() 是最基礎(chǔ)的 exec 函數(shù),所有其他 exec 系列函數(shù)都是基于它的。它直接接受路徑名、參數(shù)數(shù)組和環(huán)境變量數(shù)組。


函數(shù)原型如下:


int execve(const char *filename, char *const argv[], char *const envp[]);


參數(shù)如下:

  • filename:要執(zhí)行的文件的路徑(絕對(duì)或相對(duì)路徑)。

  • argv[]:參數(shù)列表(傳遞給程序的命令行參數(shù))。第一個(gè)參數(shù)通常是程序本身的名稱(chēng)。

  • envp[]:環(huán)境變量列表。


使用 execve() 執(zhí)行 /bin/ls,傳遞了參數(shù) -l 和環(huán)境變量 PATH。


#include <stdio.h>#include <stdlib.h>#include <unistd.h> int main(void) {    char *argv[] = {"ls", "-l", NULL};      // 參數(shù)列表    char *envp[] = {"PATH=/bin", NULL};     // 環(huán)境變量        printf("執(zhí)行 ls 程序n");        if (execve("/bin/ls", argv, envp) == -1) {        perror("execve error");    }        return 0;}

2


execl()

execl() 是 execve() 的簡(jiǎn)化版本,參數(shù)以可變長(zhǎng)度的方式傳遞(列表形式)。最后一個(gè)參數(shù)必須是 (char *) NULL。


函數(shù)原型如下:


int execl(const char *path, const char *arg, ... /* (char *) NULL */);


參數(shù)如下:

  • path:執(zhí)行文件的路徑。

  • arg:程序名稱(chēng)后接任意數(shù)量的參數(shù),最后以 NULL 結(jié)束。


以下例子調(diào)用 execl(),通過(guò)可變參數(shù)傳遞給 ls 程序。


#include <stdio.h>#include <stdlib.h>#include <unistd.h> int main(void) {    printf("使用 execl 執(zhí)行 ls 程序n");    execl("/bin/ls", "ls", "-l", (char *) NULL);  // 傳遞可變長(zhǎng)度參數(shù)列表        // 如果 exec 調(diào)用失敗,返回 -1    perror("execl error");    return 0;}

3


execlp()

execlp() 和 execl() 類(lèi)似,但它不需要提供文件的完整路徑。它會(huì)在 PATH 環(huán)境變量指定的目錄中搜索可執(zhí)行文件。


函數(shù)原型如下:


int execlp(const char *file, const char *arg, ... /* (char *) NULL */);


參數(shù)如下:

  • file:要執(zhí)行的程序名(無(wú)需完整路徑)。

  • arg:程序名稱(chēng)及其他參數(shù),最后以 NULL 結(jié)束。


以下例中,execlp() 會(huì)根據(jù) PATH 環(huán)境變量查找 ls 程序的路徑。


#include <stdio.h>#include <stdlib.h>#include <unistd.h> int main(void) {    printf("使用 execlp 執(zhí)行 ls 程序n");    execlp("ls", "ls", "-l", (char *) NULL);  // 使用環(huán)境變量中的路徑搜索 ls 程序        perror("execlp error");    return 0;}

4


execle()

execle() 類(lèi)似于 execl(),但允許傳遞環(huán)境變量數(shù)組。


函數(shù)原型如下:


int execle(const char *path, const char *arg, ... /*, (char *) NULL, char * const envp[] */);

參數(shù)如下:

  • path:可執(zhí)行文件路徑。

  • arg:程序名稱(chēng)及其他參數(shù),最后以 NULL 結(jié)束。

  • envp[]:環(huán)境變量數(shù)組。


以下例子中,execle() 將自定義的環(huán)境變量傳遞給 ls 程序。


#include <stdio.h>#include <stdlib.h>#include <unistd.h> int main(void) {    char *envp[] = {"PATH=/bin", NULL};   // 設(shè)置環(huán)境變量        printf("使用 execle 執(zhí)行 ls 程序n");    execle("/bin/ls", "ls", "-l", (char *) NULL, envp);  // 傳遞環(huán)境變量        perror("execle error");    return 0;}

5


execv()

execv() 是 execve() 的簡(jiǎn)化版本,不需要傳遞環(huán)境變量,只需要路徑和參數(shù)數(shù)組。


函數(shù)原型如下:


int execv(const char *path, char *const argv[]);


參數(shù)如下:

  • path:可執(zhí)行文件的路徑。

  • argv[]:參數(shù)數(shù)組。


在該例中,execv() 使用參數(shù)數(shù)組執(zhí)行 ls。


#include <stdio.h>#include <stdlib.h>#include <unistd.h> int main(void) {    char *argv[] = {"ls", "-l", NULL};  // 參數(shù)數(shù)組     printf("使用 execv 執(zhí)行 ls 程序n");    execv("/bin/ls", argv);  // 傳遞參數(shù)數(shù)組        perror("execv error");    return 0;}

6


execvp()

execvp() 和 execv() 類(lèi)似,但它會(huì)根據(jù) PATH 環(huán)境變量查找可執(zhí)行文件。


函數(shù)原型如下:


int execvp(const char *file, char *const argv[]);


參數(shù)如下:

  • file:可執(zhí)行文件的名稱(chēng)。

  • argv[]:參數(shù)數(shù)組。


execvp() 不要求完整路徑,會(huì)自動(dòng)在 PATH 中查找 ls。


#include <stdio.h>#include <stdlib.h>#include <unistd.h> int main(void) {    char *argv[] = {"ls", "-l", NULL};  // 參數(shù)數(shù)組     printf("使用 execvp 執(zhí)行 ls 程序n");    execvp("ls", argv);  // 根據(jù) PATH 搜索并執(zhí)行程序        perror("execvp error");    return 0;}

7


execvpe()

execvpe() 是 execvp() 的擴(kuò)展,允許傳遞自定義的環(huán)境變量。


函數(shù)原型如下:


int execvpe(const char *file, char *const argv[], char *const envp[]);


參數(shù)如下:

  • file:要執(zhí)行的程序名稱(chēng)。

  • argv[]:參數(shù)數(shù)組。

  • envp[]:環(huán)境變量數(shù)組。


在以下示例中,execvpe() 使用自定義環(huán)境變量執(zhí)行程序。


#include <stdio.h>#include <stdlib.h>#include <unistd.h> int main(void) {    char *argv[] = {"ls", "-l", NULL};  // 參數(shù)數(shù)組    char *envp[] = {"PATH=/bin", NULL}; // 環(huán)境變量     printf("使用 execvpe 執(zhí)行 ls 程序n");    execvpe("ls", argv, envp);  // 使用 PATH 環(huán)境變量執(zhí)行程序        perror("execvpe error");    return 0;}


子進(jìn)程執(zhí)行新程序時(shí),可以通過(guò) exec 系列系統(tǒng)調(diào)用替換子進(jìn)程的內(nèi)存空間,執(zhí)行新的二進(jìn)制程序。exec 系列調(diào)用的不同變體提供了靈活的參數(shù)傳遞方式,適應(yīng)不同場(chǎng)景需求。通過(guò)合理使用 fork() 和 exec(),可以實(shí)現(xiàn)高效的多進(jìn)程編程,確保資源的有效利用和進(jìn)程的靈活控制。


*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。



關(guān)鍵詞: 嵌入式 Linux

相關(guān)推薦

技術(shù)專(zhuān)區(qū)

關(guān)閉