Linux下使用exec族函數進行進程替換

在Linux下使用fork或者vfork函數創建的子進程是完全複製父進程的代碼來執行的。雖然我們可以使用fork函數返回值的不同來使得父進程和子進程執行的代碼不同。但是有時候父進程是一段c程序,子進程卻是個shell。這個時候,fork就沒法解決這個問題。因此exec函數是必須的。

exec函數族共包括6個函數,函數形式如下:

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[]);

注意:只有execve函數是系統調用,其餘的5個都是在execve基礎上封裝而來的庫函數。

函數參數的意義:

path:指定要執行的程序的名稱和路徑

file:指定要執行的程序的名稱,可以不指定路徑,但是必須配置環境變量PATH。

arg...:以逐個列舉的方式表示要執行的程序的格式:例如準備執行“創建子進程”這個程序,那麼應該傳遞參數爲:“./創建子程序”, NULL.

argv[]:以指針數組的形式表示要執行的程序的格式。

envp[]:環境變量參數。

當一個程序中使用exec函數來調用了另外的可執行文件後,那麼該進程中所有的資源完全由新進程替換。所以使用的時候應當注意,如果還想回到原來的進程繼續執行,那麼需要先使用fork函數來創建一個進程,在這個進程中使用exec函數來完成進程替換。這樣才能保證原進程能在exec調用後不被破壞。

exec函數調用後雖然替換了進程,但是卻保留PID。來段代碼跑一跑

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
    pid_t pid;
    pid = fork();
    if(0 == pid)
    {
        execl("./創建子進程","創建子進程",NULL);
    }
    if(0 < pid)
    {
        sleep(2);
        printf("I am father!\n");
    }

    return 0;
}

運行結果如下:

代碼裏的創建子進程是上一篇博客提到的代碼,在這裏。

使用fork,而不是vfork的原因是vfork會於原進程共享地址空間,fork則是複製原進程,從而創建一個原進程的副本。這樣不會破壞原進程。但是使用fork的的缺點是必須無法確定執行順序,在這裏我讓父進程掛起2秒,從而使得子進程先於父進程執行。另外使用exec函數也可以完成shell命令。例如下面的代碼。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
    pid_t pid;
    pid = fork();

    if(0 == pid)
    {
        execl("/bin/pwd","pwd",NULL);
    }
    if(0 < pid)
    {
        sleep(1);
        printf("I am father process!\n");
    }

    return 0;
}

執行結果如下:

成功執行了shell命令。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章