1. 程式人生 > >exec族函式的詳細說明

exec族函式的詳細說明

簡介

我們知道fork()函式可以建立一個和父程序相同的程式,但是我們往往需要子程序執行另一個程式,這個時候就要呼叫一種exec函式以執行另一個程式。當程序呼叫exec函式時,該程序的使用者空間程式碼和資料完全被新的程式替換,從新的程式啟動例程開始執行。呼叫exec並不建立新程式,所以呼叫exec前後該程序的id並未改變。同樣,exec後的新程序會繼承子程序很多東西,包括檔案描述符表和檔案鎖。

exec函式有六種形式

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 arg[])
int execvp(const char *file,char *const arg[])
int execve(const char *path,char *const arg[],char *const envp[])

這六個以exec開頭的函式都是根據指定的檔名找到可執行檔案,並用它來取代呼叫程序的內容,換句話說,就是在呼叫程序內部執行一個可執行檔案。

前三個含有字母l,後三個含有字母v,帶有l的代表引數列表一一列舉在函式的引數中,並要求以NULL結尾;帶有v的代表引數列表放在一個以NULL結尾的指標陣列之中(即第二個引數)。

帶有字母p的代表2個以p結尾的函式execlp和execvp,看起來,和execl與execv的差別很小,事實也如此,它們的區別從第一個引數名可以看出:除 execlp和execvp之外的4個函式都要求,它們的第1個引數path必須是一個完整的路徑,如”/bin/ls”;而execlp和execvp 的第1個引數file可以僅僅只是一個檔名,如”ls”,這兩個函式可以自動到環境變數PATH指定的目錄裡去查詢。

帶有字母e的是指給可執行檔案指定環境變數。在全部6個函式中,只有execle和execve使用了char *envp[]傳遞環境變數,其它的4個函式都沒有這個引數,這並不意味著它們不傳遞環境變數,這4個函式將把預設的環境變數不做任何修改地傳給被執行的應用程式。而execle和execve用指定的環境變數去替代預設的那些。

注意

與其他系統呼叫比起來,exec很容易失敗,被執行檔案的位置,許可權等很多因素都能導致呼叫失敗。因此,使用exec函式族時,一定要加錯誤判斷語句。
exec函式族的函式執行成功後不會返回,因為呼叫程序的實體,包括程式碼段,資料段和堆疊等都已經被新的內容取代,只有程序ID等一些表面上的資訊仍保持原樣。呼叫失敗時,會設定errno並返回-1,然後從原程式的呼叫點接著往下執行。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>

int main(int argc,char *argv[])
{
   char* arg[] = {"pwd",NULL};
   char* envp[] ={"PATH=/tmp","USER=lingdxuyan""STATUS=testing",NULL};
   //execl函式
   if(fork() == 0)
   {
      printf("execl\n");
      if(execl("/bin/ls","ls","-a",NULL) == -1)
      {
          perror("execl error");
         exit(1);
      }
    }

    execv函式
    if(fork() == 0)
    {
      printf("execv");
      if(execv("/bin/pwd",arg))
      {
         perror("execv error");
         exit(1);
      }
    }

    //execlp函式
    if(fork() == -1)
    {
        if(execlp("pwd","pwd",NULL) == -1)
        {
            perror("execp error");
            exit(1);
        }
    }

    //execvp函式
    if(fork() == 0)
    {
        if(execvp("pwd",arg) == -1)
        {
            perror("execvp error");
            exit(1);
        }
    }

    //execle函式
    if(fork() == 0)
    {
        if(execle("/bin/pwd",pwd,NULL,envp))
        {
            perror("execle error");
            exit(1);
        }
    }

    //execve函式
    if(fork() == 0)
    {
        if(execve("/bin/pwd",arg))
        {
            perror("execve error");
            exit(1);
        }
    }
}