前言? ??
? ? ? ? ? ? ? ? ??
🎬 個人主頁:@ChenPi
🐻推薦專欄1: 《Linux C應用編程(概念類)_@ChenPi的博客-CSDN博客》????
🔥 推薦專欄2: 《C++_@ChenPi的博客-CSDN博客》???
🛸推薦專欄3: ??????《鏈表_@ChenPi的博客-CSDN博客 》 ???
🌺本篇簡介 ?:? Linux進程在運行中我們如何進入到另一個進程呢?? ? ? ? ? ? ? ? ? ? ? ? ?我們可以使用exec系統調用
Linux 是一個多用戶多任務的操作系統,每個用戶可以同時運行多個程序
進程是程序運行的主體,包括進程的創建,調度和消亡的整個過程
當用戶執行一個指令或者啟動一個程序時,就創建了一個進程
一個運行的程序也可能有多個進程。
每個進程將被分配各種資源 ? ?
一 exec族函數
1.1 exec族函數函數的作用:
我們用fork函數創建新進程后,經常會在新進程中調用exec函數去執行另外一個程序。當進程調用exec函數時,該進程被完全替換為新程序。因為調用exec函數并不創建新進程,所以前后進程的ID并沒有改變。
1.2 exec函數族分別是:execl, execlp, execle, execv, execvp, execvpe
函數原型:
#include <unistd.h> extern char **environ; int execl(const char *path, const char *arg, ... /* (char *) NULL */);
int execlp(const char *file, const char *arg, ... /* (char *) NULL */);
int execle(const char *path, const char *arg, ... /*, (char *) NULL, char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
- 返回值:
- exec函數族的函數執行成功后不會返回,調用失敗時,會設置errno并返回-1,然后從原程序的調用點接著往下執行。
- 參數說明:
- path:可執行文件的路徑名字
- arg:可執行程序所帶的參數,第一個參數為可執行文件名字,沒有帶路徑且arg必須以NULL結束
- file:如果參數file中包含/,則就將其視為路徑名,否則就按 PATH環境變量,在它所指定的各目錄中搜尋可執行文件。
1.3 exec族函數的區別??
1.3.1?execl()和 execv()的區別
execl()和 execv()都是基本的 exec 函數,都可用于執行一個新程序,它們之間的區別在于:
參數格式不同,參數 path 意義和格式都相同,指向新程序的路徑名,既可以是絕對路徑、也可以是相對路徑。execl()和 execv()不同的在于第二個參數,execv()的argv 參數與 execve()的 argv 參數相同,也是字符串指針數組;而 execl()把參數列表依次排列,使 用可變參數形式傳遞,本質上也是多個字符串,以 NULL 結尾,如下所示:
// execv 傳參
char *arg_arr[5];
/*參數 argv 則指定了傳遞給新程序的命令行參數。是一個字符串數組,
該數組對應于 main(int argc, char *argv[])函數的第二個參數 argv,
且格式也與之相同,是由字符串指針所組成的數組,以 NULL 結束。*/argv[0]對應的便是新程序自身路徑名。
arg_arr[0] = "./newApp";
arg_arr[1] = "Hello";
arg_arr[2] = "World";
arg_arr[3] = NULL;
execv("./newApp", arg_arr); // execl 傳參
execl("./newApp", "./newApp", "Hello", "World", NULL);
1.3.2?execlp()和 execvp()的區別
execlp()和 execvp()在 execl()和 execv()基礎上加了一個 p,這個 p 其實表示的是 PATH;execl()和execv()要求提供新程序的路徑名,而 execlp()和 execvp()則允許只提供新程序文件名,系統會在由 環境變量 PATH 所指定的目錄列表中尋找相應的可執行文件,如果執行的新程序是一個 Linux 命 令,這將很有用;當然,execlp()和 execvp()函數也兼容相對路徑和絕對路徑的方式。
1.3.1?execle()和 execve()的區別
execle()和 execvpe()這兩個函數在命名上加了一個 e,這個 e 其實表示的是 environment 環境變量, 意味著這兩個函數可以指定自定義的環境變量列表給新程序,參數envp與系統調用execve()的envp參數相同,也是字符串指針數組,使用方式如下所示:
// execvpe 傳參
char *env_arr[5] = {"NAME=app", "AGE=25", "SEX=man", NULL};
char *arg_arr[5]; arg_arr[0] = "./newApp";
arg_arr[1] = "Hello";
arg_arr[2] = "World";
arg_arr[3] = NULL;
execvpe("./newApp", arg_arr, env_arr); // execle 傳參
execle("./newApp", "./newApp", "Hello", "World", NULL, env_arr);
二 exec族函數使用示例
6 個 exec 庫函數運行 ls 命令,并加入參數-li。
2.1 execl
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>void main()
{char ret = execl("/bin/ls","ls","-li",NULL);if(-1 == ret) //調用失敗返回-1perror("");
}
2.2?execv
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>void main()
{char *canshu[] = {"ls","-li",NULL};execv("/bin/ls",canshu);
}
2.3?execlp
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>void main()
{execlp("ls","ls","-li",NULL);
}
2.4?execvp
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>void main()
{char *canshu[] = {"ls","-li",NULL};execvp("ls",canshu);
}
2.5?execle
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
char *env_init[] = {"AA=aa","BB=bb",NULL}; //作為參數傳到下個執行文件void main()
{execle("./test","test",NULL,env_init);}
2.6?execve
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>void main()
{char *env_init[] = {"AA=aa","BB=bb",NULL}; //作為參數傳到下個執行文件char *canshu[] = {"test","-li",NULL};execve("./test",canshu,env_init);}
?2.7 總結:?
- l : 使用參數列表
- p:使用文件名,并從PATH環境進行尋找可執行文件
- v:應先構造一個指向各參數的指針數組,然后將該數組的地址作為這些函數的參數。
- e:多了envp[]數組,使用新的環境變量代替調用進程的環境變量