1. 程式人生 > >linux系統程式設計-exec函式族

linux系統程式設計-exec函式族

exec函式族

  • fork建立子程序後執行的是和父程序相同的程式(但有可能執行不同的程式碼分支),子程序往往要呼叫一種exec函式以執行另一個程式。
  • 當程序呼叫一種exec函式時,該程序的使用者空間程式碼和資料完全被新程式替換,從新程式的啟動例程開始執行。
  • 呼叫exec並不建立新程序,所以呼叫exec前後該程序的id並未改變。

execlp函式

  • int execlp(const char *file, const char *arg, …):載入一個程序,藉助PATH環境變數
  • 引數1:要載入的程式的名字(該引數需要配合PATH環境變數來使用,當PATH中所有目錄搜尋後沒 有引數1則出錯返回)
  • 引數 2、3…:argv[0]、argv[2]、…NULL(必須以NULL結尾)
  • 該函式通常用來呼叫系統程式。如:ls、date、cp、cat等命令。

例項程式碼:

   #include <stdio.h>
   #include <unistd.h>
   #include <stdlib.h>
   
   
   
   int main(void)
   {

        pid_t pid;
        pid = fork();
 
         if(pid<0)
         {
                 perror
("fork error"); exit(1); } else if(pid>1) { printf("i am parent"); sleep(1); } else { int tmp = execlp("ls","ls","-l","-a",NULL); //子程序執行 ls -al 命令 if
(tmp<0) exit(1); } return 0; }

結果:執行app程式 和 執行 ls -al 命令結果一樣

在這裡插入圖片描述

execl函式

  • int execl(const char *path, const char *arg, …):載入一個程序, 通過 路徑來載入。
  • 對比execlp,如載入 “ls” 命令帶有-l,-F引數 execlp(“ls”, “ls”, “-l”, “-F”, NULL); 使用程式名在PATH中搜索。 execl("/bin/ls", “ls”, “-l”, “-F”, NULL); 使用引數1給出的絕對路徑搜尋。

execle函式

  • int execle(const char *path, const char *arg, …, char *const envp[] ):使用路徑呼叫程式,使用新的環境變數陣列設定被呼叫的程式的環境變數

hello.c : 輸出自己pid和環境變數

 #include <stdio.h>
 #include <unistd.h>
 extern char** environ;
 
 int main(void)
{
        printf("hello pid is:%d \n" ,getpid() );
        
        int i;
        for(i=0;environ[i];i++)
                 printf("%s\n",environ[i]);
         return 0;
}

直接執行的結果: 在這裡插入圖片描述 app.c

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

 int main(void)
 {

         pid_t pid;
         pid = fork();
 
        if(pid<0)
        {
                 perror("fork error");
                 exit(1);
         }
 
         else if(pid>1)
         {
                 printf("i am parent\n");
                 sleep(1);
         }

         else
         {
              char* envp[]={"AA=BBCCDD",NULL};
              int tmp = execle("./xx/hello","app1",NULL,envp); //hello 上面的程式

                 if(tmp<0)
                 {
                         exit(1);
                         printf("child dead");
                }
         }
 
         return 0;
 }

執行結果: hello 程序的 環境變數 變成 AA=BBCCDD 在這裡插入圖片描述

execv函式

  • int execv(const char *path, char *const argv[]);
 char* argv[]={"ls", "-l","-a","NULL"};
 execv("/bin/ls",argv)

execvp函式

  • int execvp(const char *file, char *const argv[]) :
 char* argv[]={"ls", "-l","-a","NULL"};
 execv("ls",argv)// ls藉助PATH環境變數

execve函式

  • int execve(const char *path, char *const argv[], char *const envp[])

小結

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

(1)

  1. path:傳遞的是可執行程式的路徑
  2. file:可執行程式名,依靠環境變數來找
  3. arg:傳遞 “argv[0]” ,“argv[1]”,…NULL
  4. argv[]: 定義一個字串指標陣列(命令列引數) 傳進去 :char* argv[]={“ls”, “-l”,"-a",“NULL”};:
  5. envp[]: 定義一個字串指標陣列(環境變數) 傳進去: char* envp[]={“AA=BBCCDD”,NULL};

(2)

  • l (list)         命令列引數列表
  • p (path)       搜素file時使用path變數
  • v (vector)       使用命令列引數陣列
  • e (environment)   使用環境變數陣列 ,不使用程序原有的環境變數,設定新載入程式執行的環境變數

(3)

  • 事實上,只有execve是真正的系統呼叫,其它五個函式最終都呼叫execve,所以execve在man手冊第2節,其它函式在man手冊第3節。這些函式之間的關係如下圖所示。 在這裡插入圖片描述