在進程中運行新代碼 execl、execle、execlp、execv、execve和execvp函數

摘要:本文主要講述如何在進程中運行新代碼,以及exec系列函數的基本使用方法.

在進程中運行新代碼

    用函數fork創建子進程後,如果希望在當前子進程中運行新的程序,可以調用exec函數執行另一個程序.當進程調用exec函數時,該進程用戶空間資源(正文、數據、堆和棧)完全由新程序替代,新程序則從main函數開始執行.因爲調用exec函數並沒有創建新的進程,所以前後的進程ID並沒有改變,也即內核信息基本不做修改.
    exec系列函數共有7函數可供使用,這些函數的區別在於:指示新程序的位置是使用路徑還是文件名,如果是使用文件名,則在系統的PATH環境變量所描述的路徑中搜索該程序;在使用參數時使用參數列表的方式還是使用argv[]數組的方式.

1.exec系列函數

函數定義:
    #include <unistd.h>
    int execl(const char *pathname, const char *arg0, ... /* (char *)0 */ );
    int execv(const char *pathname, char *const argv[]);
    int execle(const char *pathname, const char *arg0, .../* (char *)0, char *const envp[] */ );
    int execve(const char *pathname, char *const argv[], char *const envp[]);
    int execlp(const char *filename, const char *arg0, ... /* (char *)0 */ );
    int execvp(const char *filename, char *const argv[]);
    int fexecve(int fd, char *const argv[], char *const envp[]);
返回值:如果執行成功將不返回,否則返回-1,失敗代碼存儲在errno中.
    前4個函數取路徑名作爲參數,後兩個是取文件名作爲參數,最後一個是以一個文件描述符作爲參數.

2.函數具體分析

    當指定filename作爲參數時:
1)如果filename中包含/,則將其視爲路徑名.
2)否則就按PATH環境變量,在它所指的各目錄搜尋可執行文件.

2.1 execl()函數

int execl(const char *pathname, const char *arg0, ... /* (char *)0 */ );
    execl()函數用來執行參數path字符串所指向的程序,第二個及以後的參數代表執行文件時傳遞的參數列表,最後一個參數必須是空指針以標誌參數列表爲空.
例子1:演示exec()函數的基本使用.
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
int main()
{
        pid_t pid;
        pid = fork();
        if(pid<0)
        {
                printf("error fork:%m\n");
                exit(-1);
        }
        else if(pid==0)
        {
                //
                execl("/bin/ls","ls","-l","/etc",(char *)0);
        }
        else
        {
                printf("parent process\n");
        }
        return 0;
}

輸出:

 

2.2 execle()函數

int execle(const char *pathname, const char *arg0, .../* (char *)0, char *const envp[] */ );
    execle()函數用來執行參數path字符串所指向的程序,第二個及以後的參數代表執行文件時傳遞的參數列表,最後一個參數必須指向一個新的環境變量數組,即新執行程序的環境變量.
例子2:
#include <unistd.h>
int main(int argc, char *argv[], char *env[])
{
        execle("/bin/ls","ls","-l", "/etc",(char *)0,env);
        return 0;
}

輸出:

 

2.3 execlp()函數

int execlp(const char *filename, const char *arg0, ... /* (char *)0 */ );
    execlp()函數會從PATH環境變量所指的目錄中查找文件名爲第一個參數指示的字符串,找到後執行該文件,第二個及以後的參數代表執行文件時傳遞的參數列表,最後一個參數必須是空指針.
例子3:
#include <unistd.h>

int main()
{
        execlp("ls", "ls", "-l", "/etc", (char *)0);
        return 0;
}

輸出:

 

2.4 execv()函數

int execv(const char *path, char *const argv[]);
    execv()函數函數用來執行參數path字符串所指向的程序,第二個爲數組指針維護的程序參數列表,該數組的最後一個成員必須是空指針.
例子4:
#include <unistd.h>

int main()
{
        char *argv[] = {"ls", "-l", "/etc", (char *)0};
        execv("/bin/ls", argv);
        return 0;
}

輸出:

 

2.5 execvp()函數

int execvp(const char *file, char *const argv[]);
   execvp()函數會從PATH環境變量所指的目錄中查找文件名爲第一個參數指示的字符串,找到後執行該文件,第二個及以後的參數代表執行文件時傳遞的參數列表,最後一個成員必須是空指針.
例子5:
#include <unistd.h>

int main()
{
        char *argv[] = {"ls", "-l", "/etc", (char *)0};
        execvp("ls", argv);
        return 0;
}

輸出:

 
    幾個函數之間非常相似,沒有找到更好的方法記憶,通過簡單的例子暫時瞭解一下它們之間的不同調用方式.字母聯想也不靠譜:
    字母p表示該函數取filename作爲參數,並且用PATH環境變量尋找可執行文件.
    字母l表示該函數取一個參數表,它與字母v互斥.
    字母v表示該函數取一個argv[]矢量.
    字母e表示該函數取envp[]數組.

待續......

筆者:個人能力有限,只是學習參考...讀者若發現文中錯誤,敬請提出.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------勿在浮沙築高臺,靜下心來,慢慢地沉澱---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章